diff --git a/.gitignore b/.gitignore index d712c807..f5e642e2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.pb.h *.pb.cc *.gcda +*.pyc *~ Makefile build @@ -27,4 +28,4 @@ simulators/bochs/ltdlconf.h !simulators/bochs/plex86/kernel/freebsd/Makefile -simulators/gem5/* +simulators/gem5/.hg diff --git a/simulators/gem5/.hgignore b/simulators/gem5/.hgignore new file mode 100644 index 00000000..9e4aee18 --- /dev/null +++ b/simulators/gem5/.hgignore @@ -0,0 +1,11 @@ +syntax: glob +build +parser.out +parsetab.py +cscope.files +cscope.out +*.pyc +*~ +.*.swp +m5out +src/doxygen diff --git a/simulators/gem5/.hgtags b/simulators/gem5/.hgtags new file mode 100644 index 00000000..61c0396b --- /dev/null +++ b/simulators/gem5/.hgtags @@ -0,0 +1,21 @@ +6b99127531fd692ff0f202e327d0826ed2bfcf5f m5_1.0_beta1 +1a40e60270c11ec24f11c783e70367e2740cdc56 m5_1.0_beta1 +069849384988e553b6edae71ecaf1fb6e918d738 m5_1.0_beta2 +4cfa92eca35d532b339507f1c631e1986d87b258 m5_1.0_tutorial +ffe1942d845c67fb3fd04692420c9433638eba13 m5_1.0_web +af8bf5e4e85ba1a773183cc3f6c43bcdf0ce146a m5_1.1 +1c0eeb0dae9b6a2a5479faf3ab52fb1ed0ce703f m5_1.1 +c486924ed90eb6805e8cf44ddee5ad5435c79051 m5_1.1 +01e679b66ca9474f10f8f96d391693adf76fc73a m5_1.1 +2608cd7def85c9fdc84251295c8023fab990d530 m5_1.1 +cdd48642d9bf584bd445b40abec9e7f934a5900b m5_1.1 +8d690c7c2efced99f7991b7ace56d769bae7cfdd m5_2.0_beta1 +d83885ad2b41777c97b94882aa8f07e761e55ac1 m5_2.0_beta1_patch1 +1906dcace7c27b2153bfb95ca1218660e1cc1f70 m5_2.0_beta2 +b174ae14f007ba0c341f8df77d36f57f48369cc8 m5_2.0_beta2 +91a9ac67662aa3a79315ade29b17a85961fecd88 m5_2.0_beta3 +dce5a8655829b7d2e24ce40cafc9c8873a71671f m5_2.0_beta5 +1ac44b6c87ec71a8410c9a9c219269eca71f8077 m5_2.0_beta4 +60a931b03fb165807f02bcccc4f7d0fd705a67a9 copyright_update +d8b246a665c160a31751b4091f097022cde16dd7 m5_2.0_beta6 +5de565c4b7bdf46670611858b709c1eb50ad7c5c Calvin_Submission diff --git a/simulators/gem5/COPYING b/simulators/gem5/COPYING new file mode 100644 index 00000000..ba9cb0f7 --- /dev/null +++ b/simulators/gem5/COPYING @@ -0,0 +1,47 @@ +Please see individual files for details of the license on each file. +The preferred license can be found in LICENSE. + +All files in this distribution (other than in the ext directory) have +licenses based on the BSD or MIT licenses. Some files in the ext +directory are GNU LGPL. No other licenses are found in this +distribution. + +Beyond the BSD license, some files include the following clarification +of the license as required by the copyright holder: + + The license below extends only to copyright in the software and + shall not be construed as granting a license to any other + intellectual property including but not limited to intellectual + property relating to a hardware implementation of the + functionality of the software licensed hereunder. You may use the + software subject to the license terms below provided that you + ensure that this notice is replicated unmodified and in its + entirety in all distributions of the software, modified or + unmodified, in source code or in binary form. + +The copyright holders include (not counting the ext directory): + +Copyright (c) 2000-2011 The Regents of The University of Michigan +Copyright (c) 1990,1993-1995,2007-2010 The Hewlett-Packard Development Company +Copyright (c) 1999-2009,2011 Mark D. Hill and David A. Wood +Copyright (c) 2009-2011 ARM Limited +Copyright (c) 2008-2009 Princeton University +Copyright (c) 2007 MIPS Technologies, Inc. +Copyright (c) 2009-2011 Advanced Micro Devices, Inc. +Copyright (c) 2009 The University of Edinburgh +Copyright (c) 2007-2008 The Florida State University +Copyright (c) 2010 Massachusetts Institute of Technology +Copyright (c) 1990-1993 The Regents of the University of California +Copyright (c) 2006-2009 Nathan Binkert +Copyright (c) 2001 The NetBSD Foundation, Inc. +Copyright (c) 2010-2011 Gabe Black +Copyright (c) 1994 Adam Glass +Copyright (c) 1990-1992 MIPS Computer Systems, Inc. +Copyright (c) 2004 Richard J. Wagner +Copyright (c) 2000 Computer Engineering and Communication Networks Lab +Copyright (c) 2001 Eric Jackson +Copyright (c) 1990 Hewlett-Packard Development Company +Copyright (c) 1994-1996 Carnegie-Mellon University. +Copyright (c) 1993-1994 Christopher G. Demetriou +Copyright (c) 1997-2002 Makoto Matsumoto and Takuji Nishimura +Copyright (c) 1998,2001 Manuel Bouyer. diff --git a/simulators/gem5/LICENSE b/simulators/gem5/LICENSE new file mode 100644 index 00000000..8237282c --- /dev/null +++ b/simulators/gem5/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer; +redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution; +neither the name of the copyright holders nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/simulators/gem5/README b/simulators/gem5/README new file mode 100644 index 00000000..3b6a3f6b --- /dev/null +++ b/simulators/gem5/README @@ -0,0 +1,48 @@ +This is the M5 simulator. + +For detailed information about building the simulator and getting +started please refer to http://www.m5sim.org. + +Specific pages of interest are: +http://www.m5sim.org/wiki/index.php/Compiling_M5 +http://www.m5sim.org/wiki/index.php/Running_M5 + +Short version: + +1. If you don't have SCons version 0.98.1 or newer, get it from +http://wwww.scons.org. + +2. If you don't have SWIG version 1.3.31 or newer, get it from +http://wwww.swig.org. + +3. Make sure you also have gcc version 3.4.6 or newer, Python 2.4 or newer +(the dev version with header files), zlib, and the m4 preprocessor. + +4. In this directory, type 'scons build/ALPHA_SE/tests/debug/quick'. This +will build the debug version of the m5 binary (m5.debug) for the Alpha +syscall emulation target, and run the quick regression tests on it. + +If you have questions, please send mail to m5-users@m5sim.org + +WHAT'S INCLUDED (AND NOT) +------------------------- + +The basic source release includes these subdirectories: + - m5: + - configs: simulation configuration scripts + - ext: less-common external packages needed to build m5 + - src: source code of the m5 simulator + - system: source for some optional system software for simulated systems + - tests: regression tests + - util: useful utility programs and files + +To run full-system simulations, you will need compiled system firmware +(console and PALcode for Alpha), kernel binaries and one or more disk images. +These files for Alpha are collected in a separate archive, m5_system.tar.bz2. +This file can he downloaded separately. + +Depending on the ISA used, M5 may support Linux 2.4/2.6, FreeBSD, and the +proprietary Compaq/HP Tru64 version of Unix. We are able to distribute Linux +and FreeBSD bootdisks, but we are unable to distribute bootable disk images of +Tru64 Unix. If you have a Tru64 license and are interested in +obtaining disk images, contact us at m5-users@m5sim.org diff --git a/simulators/gem5/SConstruct b/simulators/gem5/SConstruct new file mode 100755 index 00000000..b3349593 --- /dev/null +++ b/simulators/gem5/SConstruct @@ -0,0 +1,1063 @@ +# -*- mode:python -*- + +# Copyright (c) 2011 Advanced Micro Devices, Inc. +# Copyright (c) 2009 The Hewlett-Packard Development Company +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt +# Nathan Binkert + +################################################### +# +# SCons top-level build description (SConstruct) file. +# +# While in this directory ('gem5'), just type 'scons' to build the default +# configuration (see below), or type 'scons build//' +# to build some other configuration (e.g., 'build/ALPHA/gem5.opt' for +# the optimized full-system version). +# +# You can build gem5 in a different directory as long as there is a +# 'build/' somewhere along the target path. The build system +# expects that all configs under the same build directory are being +# built for the same host system. +# +# Examples: +# +# The following two commands are equivalent. The '-u' option tells +# scons to search up the directory tree for this SConstruct file. +# % cd /gem5 ; scons build/ALPHA/gem5.debug +# % cd /gem5/build/ALPHA; scons -u gem5.debug +# +# The following two commands are equivalent and demonstrate building +# in a directory outside of the source tree. The '-C' option tells +# scons to chdir to the specified directory to find this SConstruct +# file. +# % cd /gem5 ; scons /local/foo/build/ALPHA/gem5.debug +# % cd /local/foo/build/ALPHA; scons -C /gem5 gem5.debug +# +# You can use 'scons -H' to print scons options. If you're in this +# 'gem5' directory (or use -u or -C to tell scons where to find this +# file), you can use 'scons -h' to print all the gem5-specific build +# options as well. +# +################################################### + +# Check for recent-enough Python and SCons versions. +try: + # Really old versions of scons only take two options for the + # function, so check once without the revision and once with the + # revision, the first instance will fail for stuff other than + # 0.98, and the second will fail for 0.98.0 + EnsureSConsVersion(0, 98) + EnsureSConsVersion(0, 98, 1) +except SystemExit, e: + print """ +For more details, see: + http://gem5.org/Dependencies +""" + raise + +# We ensure the python version early because we have stuff that +# requires python 2.4 +try: + EnsurePythonVersion(2, 4) +except SystemExit, e: + print """ +You can use a non-default installation of the Python interpreter by +either (1) rearranging your PATH so that scons finds the non-default +'python' first or (2) explicitly invoking an alternative interpreter +on the scons script. + +For more details, see: + http://gem5.org/wiki/index.php/Using_a_non-default_Python_installation +""" + raise + +# Global Python includes +import os +import re +import subprocess +import sys + +from os import mkdir, environ +from os.path import abspath, basename, dirname, expanduser, normpath +from os.path import exists, isdir, isfile +from os.path import join as joinpath, split as splitpath + +# SCons includes +import SCons +import SCons.Node + +extra_python_paths = [ + Dir('src/python').srcnode().abspath, # gem5 includes + Dir('ext/ply').srcnode().abspath, # ply is used by several files + ] + +sys.path[1:1] = extra_python_paths + +from m5.util import compareVersions, readCommand +from m5.util.terminal import get_termcap + +help_texts = { + "options" : "", + "global_vars" : "", + "local_vars" : "" +} + +Export("help_texts") + + +# There's a bug in scons in that (1) by default, the help texts from +# AddOption() are supposed to be displayed when you type 'scons -h' +# and (2) you can override the help displayed by 'scons -h' using the +# Help() function, but these two features are incompatible: once +# you've overridden the help text using Help(), there's no way to get +# at the help texts from AddOptions. See: +# http://scons.tigris.org/issues/show_bug.cgi?id=2356 +# http://scons.tigris.org/issues/show_bug.cgi?id=2611 +# This hack lets us extract the help text from AddOptions and +# re-inject it via Help(). Ideally someday this bug will be fixed and +# we can just use AddOption directly. +def AddLocalOption(*args, **kwargs): + col_width = 30 + + help = " " + ", ".join(args) + if "help" in kwargs: + length = len(help) + if length >= col_width: + help += "\n" + " " * col_width + else: + help += " " * (col_width - length) + help += kwargs["help"] + help_texts["options"] += help + "\n" + + AddOption(*args, **kwargs) + +AddLocalOption('--colors', dest='use_colors', action='store_true', + help="Add color to abbreviated scons output") +AddLocalOption('--no-colors', dest='use_colors', action='store_false', + help="Don't add color to abbreviated scons output") +AddLocalOption('--default', dest='default', type='string', action='store', + help='Override which build_opts file to use for defaults') +AddLocalOption('--ignore-style', dest='ignore_style', action='store_true', + help='Disable style checking hooks') +AddLocalOption('--update-ref', dest='update_ref', action='store_true', + help='Update test reference outputs') +AddLocalOption('--verbose', dest='verbose', action='store_true', + help='Print full tool command lines') + +termcap = get_termcap(GetOption('use_colors')) + +######################################################################## +# +# Set up the main build environment. +# +######################################################################## +use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH', + 'PYTHONPATH', 'RANLIB', 'SWIG' ]) + +use_env = {} +for key,val in os.environ.iteritems(): + if key in use_vars or key.startswith("M5"): + use_env[key] = val + +main = Environment(ENV=use_env) +main.Decider('MD5-timestamp') +main.root = Dir(".") # The current directory (where this file lives). +main.srcdir = Dir("src") # The source directory + +# add useful python code PYTHONPATH so it can be used by subprocesses +# as well +main.AppendENVPath('PYTHONPATH', extra_python_paths) + +######################################################################## +# +# Mercurial Stuff. +# +# If the gem5 directory is a mercurial repository, we should do some +# extra things. +# +######################################################################## + +hgdir = main.root.Dir(".hg") + +mercurial_style_message = """ +You're missing the gem5 style hook, which automatically checks your code +against the gem5 style rules on hg commit and qrefresh commands. This +script will now install the hook in your .hg/hgrc file. +Press enter to continue, or ctrl-c to abort: """ + +mercurial_style_hook = """ +# The following lines were automatically added by gem5/SConstruct +# to provide the gem5 style-checking hooks +[extensions] +style = %s/util/style.py + +[hooks] +pretxncommit.style = python:style.check_style +pre-qrefresh.style = python:style.check_style +# End of SConstruct additions + +""" % (main.root.abspath) + +mercurial_lib_not_found = """ +Mercurial libraries cannot be found, ignoring style hook. If +you are a gem5 developer, please fix this and run the style +hook. It is important. +""" + +# Check for style hook and prompt for installation if it's not there. +# Skip this if --ignore-style was specified, there's no .hg dir to +# install a hook in, or there's no interactive terminal to prompt. +if not GetOption('ignore_style') and hgdir.exists() and sys.stdin.isatty(): + style_hook = True + try: + from mercurial import ui + ui = ui.ui() + ui.readconfig(hgdir.File('hgrc').abspath) + style_hook = ui.config('hooks', 'pretxncommit.style', None) and \ + ui.config('hooks', 'pre-qrefresh.style', None) + except ImportError: + print mercurial_lib_not_found + + if not style_hook: + print mercurial_style_message, + # continue unless user does ctrl-c/ctrl-d etc. + try: + raw_input() + except: + print "Input exception, exiting scons.\n" + sys.exit(1) + hgrc_path = '%s/.hg/hgrc' % main.root.abspath + print "Adding style hook to", hgrc_path, "\n" + try: + hgrc = open(hgrc_path, 'a') + hgrc.write(mercurial_style_hook) + hgrc.close() + except: + print "Error updating", hgrc_path + sys.exit(1) + + +################################################### +# +# Figure out which configurations to set up based on the path(s) of +# the target(s). +# +################################################### + +# Find default configuration & binary. +Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA/gem5.debug')) + +# helper function: find last occurrence of element in list +def rfind(l, elt, offs = -1): + for i in range(len(l)+offs, 0, -1): + if l[i] == elt: + return i + raise ValueError, "element not found" + +# Take a list of paths (or SCons Nodes) and return a list with all +# paths made absolute and ~-expanded. Paths will be interpreted +# relative to the launch directory unless a different root is provided +def makePathListAbsolute(path_list, root=GetLaunchDir()): + return [abspath(joinpath(root, expanduser(str(p)))) + for p in path_list] + +# Each target must have 'build' in the interior of the path; the +# directory below this will determine the build parameters. For +# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we +# recognize that ALPHA_SE specifies the configuration because it +# follow 'build' in the build path. + +# The funky assignment to "[:]" is needed to replace the list contents +# in place rather than reassign the symbol to a new list, which +# doesn't work (obviously!). +BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS) + +# Generate a list of the unique build roots and configs that the +# collected targets reference. +variant_paths = [] +build_root = None +for t in BUILD_TARGETS: + path_dirs = t.split('/') + try: + build_top = rfind(path_dirs, 'build', -2) + except: + print "Error: no non-leaf 'build' dir found on target path", t + Exit(1) + this_build_root = joinpath('/',*path_dirs[:build_top+1]) + if not build_root: + build_root = this_build_root + else: + if this_build_root != build_root: + print "Error: build targets not under same build root\n"\ + " %s\n %s" % (build_root, this_build_root) + Exit(1) + variant_path = joinpath('/',*path_dirs[:build_top+2]) + if variant_path not in variant_paths: + variant_paths.append(variant_path) + +# Make sure build_root exists (might not if this is the first build there) +if not isdir(build_root): + mkdir(build_root) +main['BUILDROOT'] = build_root + +Export('main') + +main.SConsignFile(joinpath(build_root, "sconsign")) + +# Default duplicate option is to use hard links, but this messes up +# when you use emacs to edit a file in the target dir, as emacs moves +# file to file~ then copies to file, breaking the link. Symbolic +# (soft) links work better. +main.SetOption('duplicate', 'soft-copy') + +# +# Set up global sticky variables... these are common to an entire build +# tree (not specific to a particular build like ALPHA_SE) +# + +global_vars_file = joinpath(build_root, 'variables.global') + +global_vars = Variables(global_vars_file, args=ARGUMENTS) + +global_vars.AddVariables( + ('CC', 'C compiler', environ.get('CC', main['CC'])), + ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])), + ('SWIG', 'SWIG tool', environ.get('SWIG', main['SWIG'])), + ('BATCH', 'Use batch pool for build and tests', False), + ('BATCH_CMD', 'Batch pool submission command name', 'qdo'), + ('M5_BUILD_CACHE', 'Cache built objects in this directory', False), + ('EXTRAS', 'Add extra directories to the compilation', '') + ) + +# Update main environment with values from ARGUMENTS & global_vars_file +global_vars.Update(main) +help_texts["global_vars"] += global_vars.GenerateHelpText(main) + +# Save sticky variable settings back to current variables file +global_vars.Save(global_vars_file, main) + +# Parse EXTRAS variable to build list of all directories where we're +# look for sources etc. This list is exported as extras_dir_list. +base_dir = main.srcdir.abspath +if main['EXTRAS']: + extras_dir_list = makePathListAbsolute(main['EXTRAS'].split(':')) +else: + extras_dir_list = [] + +Export('base_dir') +Export('extras_dir_list') + +# the ext directory should be on the #includes path +main.Append(CPPPATH=[Dir('ext')]) + +def strip_build_path(path, env): + path = str(path) + variant_base = env['BUILDROOT'] + os.path.sep + if path.startswith(variant_base): + path = path[len(variant_base):] + elif path.startswith('build/'): + path = path[6:] + return path + +# Generate a string of the form: +# common/path/prefix/src1, src2 -> tgt1, tgt2 +# to print while building. +class Transform(object): + # all specific color settings should be here and nowhere else + tool_color = termcap.Normal + pfx_color = termcap.Yellow + srcs_color = termcap.Yellow + termcap.Bold + arrow_color = termcap.Blue + termcap.Bold + tgts_color = termcap.Yellow + termcap.Bold + + def __init__(self, tool, max_sources=99): + self.format = self.tool_color + (" [%8s] " % tool) \ + + self.pfx_color + "%s" \ + + self.srcs_color + "%s" \ + + self.arrow_color + " -> " \ + + self.tgts_color + "%s" \ + + termcap.Normal + self.max_sources = max_sources + + def __call__(self, target, source, env, for_signature=None): + # truncate source list according to max_sources param + source = source[0:self.max_sources] + def strip(f): + return strip_build_path(str(f), env) + if len(source) > 0: + srcs = map(strip, source) + else: + srcs = [''] + tgts = map(strip, target) + # surprisingly, os.path.commonprefix is a dumb char-by-char string + # operation that has nothing to do with paths. + com_pfx = os.path.commonprefix(srcs + tgts) + com_pfx_len = len(com_pfx) + if com_pfx: + # do some cleanup and sanity checking on common prefix + if com_pfx[-1] == ".": + # prefix matches all but file extension: ok + # back up one to change 'foo.cc -> o' to 'foo.cc -> .o' + com_pfx = com_pfx[0:-1] + elif com_pfx[-1] == "/": + # common prefix is directory path: OK + pass + else: + src0_len = len(srcs[0]) + tgt0_len = len(tgts[0]) + if src0_len == com_pfx_len: + # source is a substring of target, OK + pass + elif tgt0_len == com_pfx_len: + # target is a substring of source, need to back up to + # avoid empty string on RHS of arrow + sep_idx = com_pfx.rfind(".") + if sep_idx != -1: + com_pfx = com_pfx[0:sep_idx] + else: + com_pfx = '' + elif src0_len > com_pfx_len and srcs[0][com_pfx_len] == ".": + # still splitting at file extension: ok + pass + else: + # probably a fluke; ignore it + com_pfx = '' + # recalculate length in case com_pfx was modified + com_pfx_len = len(com_pfx) + def fmt(files): + f = map(lambda s: s[com_pfx_len:], files) + return ', '.join(f) + return self.format % (com_pfx, fmt(srcs), fmt(tgts)) + +Export('Transform') + +# enable the regression script to use the termcap +main['TERMCAP'] = termcap + +if GetOption('verbose'): + def MakeAction(action, string, *args, **kwargs): + return Action(action, *args, **kwargs) +else: + MakeAction = Action + main['CCCOMSTR'] = Transform("CC") + main['CXXCOMSTR'] = Transform("CXX") + main['ASCOMSTR'] = Transform("AS") + main['SWIGCOMSTR'] = Transform("SWIG") + main['ARCOMSTR'] = Transform("AR", 0) + main['LINKCOMSTR'] = Transform("LINK", 0) + main['RANLIBCOMSTR'] = Transform("RANLIB", 0) + main['M4COMSTR'] = Transform("M4") + main['SHCCCOMSTR'] = Transform("SHCC") + main['SHCXXCOMSTR'] = Transform("SHCXX") +Export('MakeAction') + +CXX_version = readCommand([main['CXX'],'--version'], exception=False) +CXX_V = readCommand([main['CXX'],'-V'], exception=False) + +main['GCC'] = CXX_version and CXX_version.find('g++') >= 0 +main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0 +main['ICC'] = CXX_V and CXX_V.find('Intel') >= 0 +main['CLANG'] = CXX_version and CXX_version.find('clang') >= 0 +if main['GCC'] + main['SUNCC'] + main['ICC'] + main['CLANG'] > 1: + print 'Error: How can we have two at the same time?' + Exit(1) + +# Set up default C++ compiler flags +if main['GCC']: + main.Append(CCFLAGS=['-pipe']) + main.Append(CCFLAGS=['-fno-strict-aliasing']) + main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef']) + # Read the GCC version to check for versions with bugs + # Note CCVERSION doesn't work here because it is run with the CC + # before we override it from the command line + gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False) + main['GCC_VERSION'] = gcc_version + if not compareVersions(gcc_version, '4.4.1') or \ + not compareVersions(gcc_version, '4.4.2'): + print 'Info: Tree vectorizer in GCC 4.4.1 & 4.4.2 is buggy, disabling.' + main.Append(CCFLAGS=['-fno-tree-vectorize']) + if compareVersions(gcc_version, '4.6') >= 0: + main.Append(CXXFLAGS=['-std=c++0x']) +elif main['ICC']: + pass #Fix me... add warning flags once we clean up icc warnings +elif main['SUNCC']: + main.Append(CCFLAGS=['-Qoption ccfe']) + main.Append(CCFLAGS=['-features=gcc']) + main.Append(CCFLAGS=['-features=extensions']) + main.Append(CCFLAGS=['-library=stlport4']) + main.Append(CCFLAGS=['-xar']) + #main.Append(CCFLAGS=['-instances=semiexplicit']) +elif main['CLANG']: + clang_version_re = re.compile(".* version (\d+\.\d+)") + clang_version_match = clang_version_re.match(CXX_version) + if (clang_version_match): + clang_version = clang_version_match.groups()[0] + if compareVersions(clang_version, "2.9") < 0: + print 'Error: clang version 2.9 or newer required.' + print ' Installed version:', clang_version + Exit(1) + else: + print 'Error: Unable to determine clang version.' + Exit(1) + + main.Append(CCFLAGS=['-pipe']) + main.Append(CCFLAGS=['-fno-strict-aliasing']) + main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef']) + main.Append(CCFLAGS=['-Wno-tautological-compare']) + main.Append(CCFLAGS=['-Wno-self-assign']) + # Ruby makes frequent use of extraneous parantheses in the printing + # of if-statements + main.Append(CCFLAGS=['-Wno-parentheses']) + + if compareVersions(clang_version, "3") >= 0: + main.Append(CXXFLAGS=['-std=c++0x']) +else: + print termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal, + print "Don't know what compiler options to use for your compiler." + print termcap.Yellow + ' compiler:' + termcap.Normal, main['CXX'] + print termcap.Yellow + ' version:' + termcap.Normal, + if not CXX_version: + print termcap.Yellow + termcap.Bold + "COMMAND NOT FOUND!" +\ + termcap.Normal + else: + print CXX_version.replace('\n', '') + print " If you're trying to use a compiler other than GCC, ICC, SunCC," + print " or clang, there appears to be something wrong with your" + print " environment." + print " " + print " If you are trying to use a compiler other than those listed" + print " above you will need to ease fix SConstruct and " + print " src/SConscript to support that compiler." + Exit(1) + +# Set up common yacc/bison flags (needed for Ruby) +main['YACCFLAGS'] = '-d' +main['YACCHXXFILESUFFIX'] = '.hh' + +# Do this after we save setting back, or else we'll tack on an +# extra 'qdo' every time we run scons. +if main['BATCH']: + main['CC'] = main['BATCH_CMD'] + ' ' + main['CC'] + main['CXX'] = main['BATCH_CMD'] + ' ' + main['CXX'] + main['AS'] = main['BATCH_CMD'] + ' ' + main['AS'] + main['AR'] = main['BATCH_CMD'] + ' ' + main['AR'] + main['RANLIB'] = main['BATCH_CMD'] + ' ' + main['RANLIB'] + +if sys.platform == 'cygwin': + # cygwin has some header file issues... + main.Append(CCFLAGS=["-Wno-uninitialized"]) + +# Check for SWIG +if not main.has_key('SWIG'): + print 'Error: SWIG utility not found.' + print ' Please install (see http://www.swig.org) and retry.' + Exit(1) + +# Check for appropriate SWIG version +swig_version = readCommand([main['SWIG'], '-version'], exception='').split() +# First 3 words should be "SWIG Version x.y.z" +if len(swig_version) < 3 or \ + swig_version[0] != 'SWIG' or swig_version[1] != 'Version': + print 'Error determining SWIG version.' + Exit(1) + +min_swig_version = '1.3.34' +if compareVersions(swig_version[2], min_swig_version) < 0: + print 'Error: SWIG version', min_swig_version, 'or newer required.' + print ' Installed version:', swig_version[2] + Exit(1) + +# Set up SWIG flags & scanner +swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS') +main.Append(SWIGFLAGS=swig_flags) + +# filter out all existing swig scanners, they mess up the dependency +# stuff for some reason +scanners = [] +for scanner in main['SCANNERS']: + skeys = scanner.skeys + if skeys == '.i': + continue + + if isinstance(skeys, (list, tuple)) and '.i' in skeys: + continue + + scanners.append(scanner) + +# add the new swig scanner that we like better +from SCons.Scanner import ClassicCPP as CPPScanner +swig_inc_re = '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")' +scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re)) + +# replace the scanners list that has what we want +main['SCANNERS'] = scanners + +# Add a custom Check function to the Configure context so that we can +# figure out if the compiler adds leading underscores to global +# variables. This is needed for the autogenerated asm files that we +# use for embedding the python code. +def CheckLeading(context): + context.Message("Checking for leading underscore in global variables...") + # 1) Define a global variable called x from asm so the C compiler + # won't change the symbol at all. + # 2) Declare that variable. + # 3) Use the variable + # + # If the compiler prepends an underscore, this will successfully + # link because the external symbol 'x' will be called '_x' which + # was defined by the asm statement. If the compiler does not + # prepend an underscore, this will not successfully link because + # '_x' will have been defined by assembly, while the C portion of + # the code will be trying to use 'x' + ret = context.TryLink(''' + asm(".globl _x; _x: .byte 0"); + extern int x; + int main() { return x; } + ''', extension=".c") + context.env.Append(LEADING_UNDERSCORE=ret) + context.Result(ret) + return ret + +# Platform-specific configuration. Note again that we assume that all +# builds under a given build root run on the same host platform. +conf = Configure(main, + conf_dir = joinpath(build_root, '.scons_config'), + log_file = joinpath(build_root, 'scons_config.log'), + custom_tests = { 'CheckLeading' : CheckLeading }) + +# Check for leading underscores. Don't really need to worry either +# way so don't need to check the return code. +conf.CheckLeading() + +# Check if we should compile a 64 bit binary on Mac OS X/Darwin +try: + import platform + uname = platform.uname() + if uname[0] == 'Darwin' and compareVersions(uname[2], '9.0.0') >= 0: + if int(readCommand('sysctl -n hw.cpu64bit_capable')[0]): + main.Append(CCFLAGS=['-arch', 'x86_64']) + main.Append(CFLAGS=['-arch', 'x86_64']) + main.Append(LINKFLAGS=['-arch', 'x86_64']) + main.Append(ASFLAGS=['-arch', 'x86_64']) +except: + pass + +# Recent versions of scons substitute a "Null" object for Configure() +# when configuration isn't necessary, e.g., if the "--help" option is +# present. Unfortuantely this Null object always returns false, +# breaking all our configuration checks. We replace it with our own +# more optimistic null object that returns True instead. +if not conf: + def NullCheck(*args, **kwargs): + return True + + class NullConf: + def __init__(self, env): + self.env = env + def Finish(self): + return self.env + def __getattr__(self, mname): + return NullCheck + + conf = NullConf(main) + +# Find Python include and library directories for embedding the +# interpreter. For consistency, we will use the same Python +# installation used to run scons (and thus this script). If you want +# to link in an alternate version, see above for instructions on how +# to invoke scons with a different copy of the Python interpreter. +from distutils import sysconfig + +py_getvar = sysconfig.get_config_var + +py_debug = getattr(sys, 'pydebug', False) +py_version = 'python' + py_getvar('VERSION') + (py_debug and "_d" or "") + +py_general_include = sysconfig.get_python_inc() +py_platform_include = sysconfig.get_python_inc(plat_specific=True) +py_includes = [ py_general_include ] +if py_platform_include != py_general_include: + py_includes.append(py_platform_include) + +py_lib_path = [ py_getvar('LIBDIR') ] +# add the prefix/lib/pythonX.Y/config dir, but only if there is no +# shared library in prefix/lib/. +if not py_getvar('Py_ENABLE_SHARED'): + py_lib_path.append(py_getvar('LIBPL')) + +py_libs = [] +for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split(): + if not lib.startswith('-l'): + # Python requires some special flags to link (e.g. -framework + # common on OS X systems), assume appending preserves order + main.Append(LINKFLAGS=[lib]) + else: + lib = lib[2:] + if lib not in py_libs: + py_libs.append(lib) +py_libs.append(py_version) + +main.Append(CPPPATH=py_includes) +main.Append(LIBPATH=py_lib_path) + +# Cache build files in the supplied directory. +if main['M5_BUILD_CACHE']: + print 'Using build cache located at', main['M5_BUILD_CACHE'] + CacheDir(main['M5_BUILD_CACHE']) + + +# verify that this stuff works +if not conf.CheckHeader('Python.h', '<>'): + print "Error: can't find Python.h header in", py_includes + Exit(1) + +for lib in py_libs: + if not conf.CheckLib(lib): + print "Error: can't find library %s required by python" % lib + Exit(1) + +# On Solaris you need to use libsocket for socket ops +if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'): + if not conf.CheckLibWithHeader('socket', 'sys/socket.h', 'C++', 'accept(0,0,0);'): + print "Can't find library with socket calls (e.g. accept())" + Exit(1) + +# Check for zlib. If the check passes, libz will be automatically +# added to the LIBS environment variable. +if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++','zlibVersion();'): + print 'Error: did not find needed zlib compression library '\ + 'and/or zlib.h header file.' + print ' Please install zlib and try again.' + Exit(1) + +# Check for librt. +have_posix_clock = \ + conf.CheckLibWithHeader(None, 'time.h', 'C', + 'clock_nanosleep(0,0,NULL,NULL);') or \ + conf.CheckLibWithHeader('rt', 'time.h', 'C', + 'clock_nanosleep(0,0,NULL,NULL);') + +if conf.CheckLib('tcmalloc_minimal'): + have_tcmalloc = True +else: + have_tcmalloc = False + print termcap.Yellow + termcap.Bold + \ + "You can get a 12% performance improvement by installing tcmalloc "\ + "(libgoogle-perftools-dev package on Ubuntu or RedHat)." + \ + termcap.Normal + +if not have_posix_clock: + print "Can't find library for POSIX clocks." + +# Check for (C99 FP environment control) +have_fenv = conf.CheckHeader('fenv.h', '<>') +if not have_fenv: + print "Warning: Header file not found." + print " This host has no IEEE FP rounding mode control." + +###################################################################### +# +# Finish the configuration +# +main = conf.Finish() + +###################################################################### +# +# Collect all non-global variables +# + +# Define the universe of supported ISAs +all_isa_list = [ ] +Export('all_isa_list') + +class CpuModel(object): + '''The CpuModel class encapsulates everything the ISA parser needs to + know about a particular CPU model.''' + + # Dict of available CPU model objects. Accessible as CpuModel.dict. + dict = {} + list = [] + defaults = [] + + # Constructor. Automatically adds models to CpuModel.dict. + def __init__(self, name, filename, includes, strings, default=False): + self.name = name # name of model + self.filename = filename # filename for output exec code + self.includes = includes # include files needed in exec file + # The 'strings' dict holds all the per-CPU symbols we can + # substitute into templates etc. + self.strings = strings + + # This cpu is enabled by default + self.default = default + + # Add self to dict + if name in CpuModel.dict: + raise AttributeError, "CpuModel '%s' already registered" % name + CpuModel.dict[name] = self + CpuModel.list.append(name) + +Export('CpuModel') + +# Sticky variables get saved in the variables file so they persist from +# one invocation to the next (unless overridden, in which case the new +# value becomes sticky). +sticky_vars = Variables(args=ARGUMENTS) +Export('sticky_vars') + +# Sticky variables that should be exported +export_vars = [] +Export('export_vars') + +# Walk the tree and execute all SConsopts scripts that wil add to the +# above variables +if not GetOption('verbose'): + print "Reading SConsopts" +for bdir in [ base_dir ] + extras_dir_list: + if not isdir(bdir): + print "Error: directory '%s' does not exist" % bdir + Exit(1) + for root, dirs, files in os.walk(bdir): + if 'SConsopts' in files: + if GetOption('verbose'): + print "Reading", joinpath(root, 'SConsopts') + SConscript(joinpath(root, 'SConsopts')) + +all_isa_list.sort() + +sticky_vars.AddVariables( + EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list), + ListVariable('CPU_MODELS', 'CPU models', + sorted(n for n,m in CpuModel.dict.iteritems() if m.default), + sorted(CpuModel.list)), + BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger', + False), + BoolVariable('SS_COMPATIBLE_FP', + 'Make floating-point results compatible with SimpleScalar', + False), + BoolVariable('USE_SSE2', + 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts', + False), + BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', have_posix_clock), + BoolVariable('USE_FENV', 'Use IEEE mode control', have_fenv), + BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability', False), + ) + +# These variables get exported to #defines in config/*.hh (see src/SConscript). +export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', + 'TARGET_ISA', 'CP_ANNOTATE', 'USE_POSIX_CLOCK' ] + +################################################### +# +# Define a SCons builder for configuration flag headers. +# +################################################### + +# This function generates a config header file that #defines the +# variable symbol to the current variable setting (0 or 1). The source +# operands are the name of the variable and a Value node containing the +# value of the variable. +def build_config_file(target, source, env): + (variable, value) = [s.get_contents() for s in source] + f = file(str(target[0]), 'w') + print >> f, '#define', variable, value + f.close() + return None + +# Combine the two functions into a scons Action object. +config_action = MakeAction(build_config_file, Transform("CONFIG H", 2)) + +# The emitter munges the source & target node lists to reflect what +# we're really doing. +def config_emitter(target, source, env): + # extract variable name from Builder arg + variable = str(target[0]) + # True target is config header file + target = joinpath('config', variable.lower() + '.hh') + val = env[variable] + if isinstance(val, bool): + # Force value to 0/1 + val = int(val) + elif isinstance(val, str): + val = '"' + val + '"' + + # Sources are variable name & value (packaged in SCons Value nodes) + return ([target], [Value(variable), Value(val)]) + +config_builder = Builder(emitter = config_emitter, action = config_action) + +main.Append(BUILDERS = { 'ConfigFile' : config_builder }) + +# libelf build is shared across all configs in the build root. +main.SConscript('ext/libelf/SConscript', + variant_dir = joinpath(build_root, 'libelf')) + +# gzstream build is shared across all configs in the build root. +main.SConscript('ext/gzstream/SConscript', + variant_dir = joinpath(build_root, 'gzstream')) + +################################################### +# +# This function is used to set up a directory with switching headers +# +################################################### + +main['ALL_ISA_LIST'] = all_isa_list +def make_switching_dir(dname, switch_headers, env): + # Generate the header. target[0] is the full path of the output + # header to generate. 'source' is a dummy variable, since we get the + # list of ISAs from env['ALL_ISA_LIST']. + def gen_switch_hdr(target, source, env): + fname = str(target[0]) + f = open(fname, 'w') + isa = env['TARGET_ISA'].lower() + print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname)) + f.close() + + # Build SCons Action object. 'varlist' specifies env vars that this + # action depends on; when env['ALL_ISA_LIST'] changes these actions + # should get re-executed. + switch_hdr_action = MakeAction(gen_switch_hdr, + Transform("GENERATE"), varlist=['ALL_ISA_LIST']) + + # Instantiate actions for each header + for hdr in switch_headers: + env.Command(hdr, [], switch_hdr_action) +Export('make_switching_dir') + +################################################### +# +# Define build environments for selected configurations. +# +################################################### + +for variant_path in variant_paths: + print "Building in", variant_path + + # Make a copy of the build-root environment to use for this config. + env = main.Clone() + env['BUILDDIR'] = variant_path + + # variant_dir is the tail component of build path, and is used to + # determine the build parameters (e.g., 'ALPHA_SE') + (build_root, variant_dir) = splitpath(variant_path) + + # Set env variables according to the build directory config. + sticky_vars.files = [] + # Variables for $BUILD_ROOT/$VARIANT_DIR are stored in + # $BUILD_ROOT/variables/$VARIANT_DIR so you can nuke + # $BUILD_ROOT/$VARIANT_DIR without losing your variables settings. + current_vars_file = joinpath(build_root, 'variables', variant_dir) + if isfile(current_vars_file): + sticky_vars.files.append(current_vars_file) + print "Using saved variables file %s" % current_vars_file + else: + # Build dir-specific variables file doesn't exist. + + # Make sure the directory is there so we can create it later + opt_dir = dirname(current_vars_file) + if not isdir(opt_dir): + mkdir(opt_dir) + + # Get default build variables from source tree. Variables are + # normally determined by name of $VARIANT_DIR, but can be + # overridden by '--default=' arg on command line. + default = GetOption('default') + opts_dir = joinpath(main.root.abspath, 'build_opts') + if default: + default_vars_files = [joinpath(build_root, 'variables', default), + joinpath(opts_dir, default)] + else: + default_vars_files = [joinpath(opts_dir, variant_dir)] + existing_files = filter(isfile, default_vars_files) + if existing_files: + default_vars_file = existing_files[0] + sticky_vars.files.append(default_vars_file) + print "Variables file %s not found,\n using defaults in %s" \ + % (current_vars_file, default_vars_file) + else: + print "Error: cannot find variables file %s or " \ + "default file(s) %s" \ + % (current_vars_file, ' or '.join(default_vars_files)) + Exit(1) + + # Apply current variable settings to env + sticky_vars.Update(env) + + help_texts["local_vars"] += \ + "Build variables for %s:\n" % variant_dir \ + + sticky_vars.GenerateHelpText(env) + + # Process variable settings. + + if not have_fenv and env['USE_FENV']: + print "Warning: not available; " \ + "forcing USE_FENV to False in", variant_dir + "." + env['USE_FENV'] = False + + if not env['USE_FENV']: + print "Warning: No IEEE FP rounding mode control in", variant_dir + "." + print " FP results may deviate slightly from other platforms." + + if env['EFENCE']: + env.Append(LIBS=['efence']) + + # Save sticky variable settings back to current variables file + sticky_vars.Save(current_vars_file, env) + + if env['USE_SSE2']: + env.Append(CCFLAGS=['-msse2']) + + if have_tcmalloc: + env.Append(LIBS=['tcmalloc_minimal']) + + # The src/SConscript file sets up the build rules in 'env' according + # to the configured variables. It returns a list of environments, + # one for each variant build (debug, opt, etc.) + envList = SConscript('src/SConscript', variant_dir = variant_path, + exports = 'env') + + # Set up the regression tests for each build. + for e in envList: + SConscript('tests/SConscript', + variant_dir = joinpath(variant_path, 'tests', e.Label), + exports = { 'env' : e }, duplicate = False) + +# base help text +Help(''' +Usage: scons [scons options] [build variables] [target(s)] + +Extra scons options: +%(options)s + +Global build variables: +%(global_vars)s + +%(local_vars)s +''' % help_texts) diff --git a/simulators/gem5/build_opts/ALPHA b/simulators/gem5/build_opts/ALPHA new file mode 100644 index 00000000..38439409 --- /dev/null +++ b/simulators/gem5/build_opts/ALPHA @@ -0,0 +1,4 @@ +TARGET_ISA = 'alpha' +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MI_example' diff --git a/simulators/gem5/build_opts/ALPHA_MESI_CMP_directory b/simulators/gem5/build_opts/ALPHA_MESI_CMP_directory new file mode 100644 index 00000000..32eeb0d1 --- /dev/null +++ b/simulators/gem5/build_opts/ALPHA_MESI_CMP_directory @@ -0,0 +1,3 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MESI_CMP_directory' diff --git a/simulators/gem5/build_opts/ALPHA_MOESI_CMP_directory b/simulators/gem5/build_opts/ALPHA_MOESI_CMP_directory new file mode 100644 index 00000000..be42e636 --- /dev/null +++ b/simulators/gem5/build_opts/ALPHA_MOESI_CMP_directory @@ -0,0 +1,3 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MOESI_CMP_directory' diff --git a/simulators/gem5/build_opts/ALPHA_MOESI_CMP_token b/simulators/gem5/build_opts/ALPHA_MOESI_CMP_token new file mode 100644 index 00000000..0c94391f --- /dev/null +++ b/simulators/gem5/build_opts/ALPHA_MOESI_CMP_token @@ -0,0 +1,3 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MOESI_CMP_token' diff --git a/simulators/gem5/build_opts/ALPHA_MOESI_hammer b/simulators/gem5/build_opts/ALPHA_MOESI_hammer new file mode 100644 index 00000000..99e8f685 --- /dev/null +++ b/simulators/gem5/build_opts/ALPHA_MOESI_hammer @@ -0,0 +1,3 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MOESI_hammer' diff --git a/simulators/gem5/build_opts/ALPHA_Network_test b/simulators/gem5/build_opts/ALPHA_Network_test new file mode 100644 index 00000000..90bec0c2 --- /dev/null +++ b/simulators/gem5/build_opts/ALPHA_Network_test @@ -0,0 +1,3 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'Network_test' diff --git a/simulators/gem5/build_opts/ARM b/simulators/gem5/build_opts/ARM new file mode 100644 index 00000000..9c27c0d2 --- /dev/null +++ b/simulators/gem5/build_opts/ARM @@ -0,0 +1,3 @@ +TARGET_ISA = 'arm' +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU' +PROTOCOL = 'MI_example' diff --git a/simulators/gem5/build_opts/MIPS b/simulators/gem5/build_opts/MIPS new file mode 100644 index 00000000..82a9d624 --- /dev/null +++ b/simulators/gem5/build_opts/MIPS @@ -0,0 +1,3 @@ +TARGET_ISA = 'mips' +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MI_example' diff --git a/simulators/gem5/build_opts/NOISA b/simulators/gem5/build_opts/NOISA new file mode 100644 index 00000000..dd1f82a7 --- /dev/null +++ b/simulators/gem5/build_opts/NOISA @@ -0,0 +1,2 @@ +TARGET_ISA = 'no' +CPU_MODELS = 'no' diff --git a/simulators/gem5/build_opts/POWER b/simulators/gem5/build_opts/POWER new file mode 100644 index 00000000..672046ce --- /dev/null +++ b/simulators/gem5/build_opts/POWER @@ -0,0 +1,3 @@ +TARGET_ISA = 'power' +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU' +PROTOCOL = 'MI_example' diff --git a/simulators/gem5/build_opts/SPARC b/simulators/gem5/build_opts/SPARC new file mode 100644 index 00000000..e992b8cd --- /dev/null +++ b/simulators/gem5/build_opts/SPARC @@ -0,0 +1,3 @@ +TARGET_ISA = 'sparc' +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MI_example' diff --git a/simulators/gem5/build_opts/X86 b/simulators/gem5/build_opts/X86 new file mode 100644 index 00000000..64d163c5 --- /dev/null +++ b/simulators/gem5/build_opts/X86 @@ -0,0 +1,3 @@ +TARGET_ISA = 'x86' +CPU_MODELS = 'AtomicSimpleCPU,O3CPU,TimingSimpleCPU' +PROTOCOL = 'MI_example' diff --git a/simulators/gem5/build_opts/X86_MESI_CMP_directory b/simulators/gem5/build_opts/X86_MESI_CMP_directory new file mode 100644 index 00000000..67512cad --- /dev/null +++ b/simulators/gem5/build_opts/X86_MESI_CMP_directory @@ -0,0 +1,3 @@ +TARGET_ISA = 'x86' +CPU_MODELS = 'TimingSimpleCPU,O3CPU' +PROTOCOL = 'MESI_CMP_directory' diff --git a/simulators/gem5/configs/boot/ammp.rcS b/simulators/gem5/configs/boot/ammp.rcS new file mode 100644 index 00000000..485244c3 --- /dev/null +++ b/simulators/gem5/configs/boot/ammp.rcS @@ -0,0 +1,12 @@ +#!/bin/sh + +cd /benchmarks/spec/ammp00/ + +/sbin/m5 checkpoint 0 0 +/sbin/m5 checkpoint 100000000 200000000 + +/sbin/m5 loadsymbol + +/sbin/m5 resetstats +./ammp < input/mdred.in +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/ammp.symbol b/simulators/gem5/configs/boot/ammp.symbol new file mode 100644 index 00000000..93ef4055 --- /dev/null +++ b/simulators/gem5/configs/boot/ammp.symbol @@ -0,0 +1,257 @@ +000000012001da40 T AMMPmonitor +000000012001dfc0 T AMMPmonitor_mute +0000000120034338 D _DYNAMIC +00000001200346c8 D _GLOBAL_OFFSET_TABLE_ +0000000120034d60 G _IO_stdin_used +0000000120034500 T _PROCEDURE_LINKAGE_TABLE_ +00000001200344e0 d __CTOR_END__ +00000001200344d8 d __CTOR_LIST__ +00000001200344f0 d __DTOR_END__ +00000001200344e8 d __DTOR_LIST__ +0000000120034334 r __FRAME_END__ +00000001200344f8 d __JCR_END__ +00000001200344f8 d __JCR_LIST__ +0000000120034da0 A __bss_start +00000001200328c8 D __data_start +0000000120020c40 t __do_global_ctors_aux +0000000120001090 t __do_global_dtors_aux +0000000120034d68 G __dso_handle +00000001200328c8 A __fini_array_end +00000001200328c8 A __fini_array_start +00000001200328c8 A __init_array_end +00000001200328c8 A __init_array_start +0000000120020ba0 T __libc_csu_fini +0000000120020af0 T __libc_csu_init +0000000120001050 W __start +0000000120034da0 A _edata +0000000120035418 A _end +0000000120020ca0 T _fini +0000000120000fe8 T _init +0000000120001050 T _start +000000012000d220 T a_angle +000000012000b3d0 T a_bond +000000012000e1b0 T a_c_angle +0000000120009cd0 T a_d_zero +0000000120009c90 T a_f_zero +0000000120009f70 T a_ftodx +000000012000a000 T a_ftogx +000000012000a090 T a_ftovx +0000000120009d20 T a_g_zero +0000000120010950 T a_hybrid +000000012000a7c0 T a_inactive_f_zero +0000000120009e50 T a_inc_d +0000000120009dc0 T a_inc_f +0000000120009ee0 T a_inc_v +000000012000a370 T a_l2_d +000000012000a220 T a_l2_f +000000012000a290 T a_l2_g +000000012000a300 T a_l2_v +0000000120008bf0 T a_m_serial +000000012000a1a0 T a_max_d +000000012000a120 T a_max_f +000000012000d570 T a_mmangle +000000012000b620 T a_mmbond +0000000120009c30 T a_next +0000000120005350 T a_noel +0000000120004700 T a_nonbon +0000000120009bc0 T a_number +00000001200096b0 T a_pr_beta +000000012000a660 T a_readvelocity +0000000120020750 T a_restrain +000000012001eda0 T a_tether +000000012001a2e0 T a_torsion +0000000120009d70 T a_v_zero +0000000120003c90 T aaerror +0000000120009a60 T activate +000000012001fef0 T alltether +0000000120004370 T analyze +000000012000c0d0 T angle +0000000120034df8 S angle_first +0000000120034e00 S angle_last +0000000120034dd0 s ap.2 +0000000120034de0 s ap.4 +0000000120008970 T atom +0000000120034dc8 s atomNUMBER +0000000120034dcc s atomUPDATE +000000012000a8b0 T bond +0000000120034de8 S bond_first +0000000120034df0 S bond_last +000000012000bf20 T bond_length +000000012001f240 T bstrot +0000000120034ea0 b buff.0 +000000012001ad40 T cngdel +0000000120034da0 s completed.1 +00000001200200c0 T cpyvec +00000001200328c8 W data_start +0000000120034d98 g dielecold.0 +000000012000efe0 T dump_angles +0000000120008d00 T dump_atoms +000000012000be40 T dump_bonds +000000012000a3e0 T dump_excludes +000000012000a6c0 T dump_force +0000000120011a50 T dump_hybrids +0000000120005c20 T dump_noels +0000000120008f40 T dump_pdb +0000000120020a10 T dump_restrains +000000012001ffe0 T dump_tethers +0000000120017b30 T dump_tgroup +000000012001a170 T dump_torsions +000000012001b7a0 T dump_variable +000000012000a590 T dump_velocity +0000000120034d7c g echo.0 +0000000120001760 T eval +000000012000c580 T f_angle +000000012000ac60 T f_bond +0000000120001230 T f_box +000000012000dc50 T f_c_angle +000000012000ea10 T f_ho_angle +000000012000bab0 T f_ho_bond +0000000120011020 T f_ho_hybrid +0000000120005840 T f_ho_noel +000000012001fca0 T f_ho_tether +00000001200102b0 T f_hybrid +000000012000cd10 T f_mmangle +000000012000b0e0 T f_mmbond +0000000120005060 T f_noel +00000001200155d0 T f_nonbon +0000000120020500 T f_restrain +000000012001ebd0 T f_tether +0000000120019850 T f_torsion +000000012000fbd0 T f_trace +0000000120034db8 S first +0000000120035058 B forces +0000000120001130 t frame_dummy +0000000120014b20 T fv_update_nonbon +0000000120034e58 s fx.0 +0000000120034e60 s fy.1 +0000000120034e68 s fz.2 +000000012000ef40 T get_angle +000000012000bda0 T get_bond +000000012000c050 T get_bond_pointer +000000012001b6e0 T get_f_variable +00000001200119b0 T get_hybrid +000000012001b740 T get_i_variable +0000000120005b80 T get_noel +0000000120020970 T get_restrain +000000012001a9f0 T get_torsion +00000001200184a0 T get_torsion_value +000000012001ca50 T getatomdata +000000012000f130 T gsdg +000000012000e5a0 T gsdg_angle +000000012000bfc0 T gsdg_bond +000000012000f810 T gsdg_dgeom +0000000120011790 T gsdg_hybrid +000000012000f6c0 T gsdg_line_search +0000000120005d30 T gsdg_noel +000000012001a850 T gsdg_torsion +0000000120034d84 g highest.0 +0000000120007490 T hpac +000000012000fe30 T hybrid +0000000120034e08 S hybrid_first +0000000120034e10 S hybrid_last +0000000120034e70 S in_mom_list +0000000120009920 T inactivate +00000001200097a0 T inactivate_non_zero +0000000120034d80 g inloop.1 +0000000120034e74 s ip.1 +0000000120034e78 s jp.2 +0000000120034e7c s kp.3 +0000000120034dc0 S last +0000000120034dd8 s lastmatched.3 +000000012001b0d0 T linmin +0000000120003f80 T loadloop +0000000120034e28 s local.3 +0000000120034d88 g lowest.1 +0000000120034e20 s lsize.2 +0000000120001180 T main +0000000120017c10 T match_tgroup +000000012001b450 T match_variable +000000012001b860 T math +000000012001cd40 T math_findlabel +000000012001ccb0 T math_match_atom +0000000120020100 T matmul +0000000120012b90 T mm_fv_update_nonbon +000000012001cef0 T mom +000000012001d3f0 T mom_add +000000012001d900 T mom_jab +00000001200350f8 B mom_list +000000012001d890 T mom_param +000000012001d600 T mom_solve +0000000120004c70 T noel +0000000120034da8 S noel_first +0000000120034db0 S noel_last +0000000120034d78 G nused +0000000120034e18 s oldatomnumber.0 +0000000120034d90 g oldcutoff.4 +0000000120034d70 g p.0 +0000000120006430 T pac +0000000120006dd0 T pacpac +00000001200350a8 B potentials +0000000120007ac0 T ppac +0000000120008180 T ptpac +000000012001e840 T rand3 +000000012001e480 T randf +000000012001e760 T randg +0000000120001550 T read_eval_do +00000001200201c0 T restrain +0000000120034e90 S restrain_first +0000000120034e98 S restrain_last +000000012001b4e0 T set_f_variable +000000012001b5e0 T set_i_variable +0000000120018730 T set_torsion +000000012001e2a0 T significance +0000000120034e1c s since.1 +000000012001aa90 T steep +0000000120018f50 T tailor_exclude +0000000120018d30 T tailor_include +0000000120019110 T tailor_qab +000000012001e940 T tether +0000000120034e80 S tether_first +0000000120034e88 S tether_last +00000001200171f0 T tg_apply +0000000120017490 T tg_d_apply +0000000120016fd0 T tg_do_search +0000000120034e30 S tg_first +0000000120017a20 T tg_gen_con +0000000120016b90 T tg_init +0000000120017700 T tg_nonbon +0000000120016220 T tgroup +0000000120004220 T tisint +0000000120003cd0 T tisvariable +00000001200189e0 T tmap +0000000120017ec0 T tmin +0000000120019190 T torsion +0000000120034e38 S torsion_first +0000000120034e40 S torsion_last +0000000120006840 T tpac +0000000120016800 T tsearch +0000000120017c80 T tset +0000000120018200 T tset_bond_build +0000000120012100 T u_f_nonbon +0000000120011b60 T u_v_nonbon +0000000120012770 T uselist +000000012000c310 T v_angle +000000012000aac0 T v_bond +0000000120001540 T v_box +000000012000d930 T v_c_angle +000000012000e750 T v_ho_angle +000000012000b8a0 T v_ho_bond +0000000120010ce0 T v_ho_hybrid +00000001200055e0 T v_ho_noel +000000012001faf0 T v_ho_tether +000000012000fff0 T v_hybrid +0000000120005dc0 T v_maxwell +000000012000ca20 T v_mmangle +000000012000aef0 T v_mmbond +0000000120004e60 T v_noel +0000000120015a80 T v_nonbon +0000000120005fd0 T v_rescale +0000000120020360 T v_restrain +000000012001eab0 T v_tether +00000001200193e0 T v_torsion +000000012000f990 T v_trace +000000012001c6f0 T validatom +0000000120034e48 S variableFIRST +0000000120034e50 S variableLAST +00000001200061a0 T verlet +0000000120015ec0 T zone_nonbon diff --git a/simulators/gem5/configs/boot/art.rcS b/simulators/gem5/configs/boot/art.rcS new file mode 100644 index 00000000..caca5889 --- /dev/null +++ b/simulators/gem5/configs/boot/art.rcS @@ -0,0 +1,7 @@ +#!/bin/sh + +#/benchmarks/spec/art00/art -scanfile c756hel.in -trainfile1 a10.img -stride 2 -startx 134 -starty 220 -endx 184 -endy 240 -objects 3 +cd /benchmarks/spec/art00/ +/sbin/m5 resetstats +/benchmarks/spec/art00/art -scanfile c756hel.in -trainfile1 a10.img -stride 5 -startx 134 -starty 220 -endx 184 -endy 240 -objects 1 +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/bbench-gb.rcS b/simulators/gem5/configs/boot/bbench-gb.rcS new file mode 100644 index 00000000..e9225c02 --- /dev/null +++ b/simulators/gem5/configs/boot/bbench-gb.rcS @@ -0,0 +1,38 @@ +#!/system/bin/sh + +#Author: Anthony Gutierrez +# run script for bbench on gingerbread + +stop_m5() { + /sbin/m5 exit + + return +} + +wait_bb_finishfifo() { + echo "FINISH

FINISH

" > /data/bbench/finish_fifo.html + + return +} + +mkfifo_bbench() { + mkfifo /data/bbench/finish_fifo.html + + return +} + +run_bbench_test() { + mkfifo_bbench + am start -n com.android.browser/.BrowserActivity + wait_bb_finishfifo + + rm /data/bbench/finish_fifo.html + stop_m5 + + return +} + +sleep 10 +/sbin/m5 dumpstats +/sbin/m5 resetstats +run_bbench_test diff --git a/simulators/gem5/configs/boot/bbench-ics.rcS b/simulators/gem5/configs/boot/bbench-ics.rcS new file mode 100644 index 00000000..1bb67d9f --- /dev/null +++ b/simulators/gem5/configs/boot/bbench-ics.rcS @@ -0,0 +1,38 @@ +#!/system/bin/sh + +#Author: Anthony Gutierrez +# run script for bbench on ics + +stop_m5() { + /sbin/m5 exit + + return +} + +wait_bb_finishfifo() { + echo "FINISH

FINISH

" > /data/bbench/finish_fifo.html + + return +} + +mkfifo_bbench() { + /sbin/busybox mkfifo /data/bbench/finish_fifo.html + + return +} + +run_bbench_test() { + mkfifo_bbench + am start -a android.intent.action.VIEW -d file:///data/bbench/index.html -t application/x-webarchive-xml + wait_bb_finishfifo + + rm /data/bbench/finish_fifo.html + stop_m5 + + return +} + +sleep 10 +/sbin/m5 dumpstats +/sbin/m5 resetstats +run_bbench_test diff --git a/simulators/gem5/configs/boot/bbench.rcS b/simulators/gem5/configs/boot/bbench.rcS new file mode 100644 index 00000000..fd2ac0f5 --- /dev/null +++ b/simulators/gem5/configs/boot/bbench.rcS @@ -0,0 +1,43 @@ +#!/bin/sh + +#Author: Anthony Gutierrez + +stop_m5() { + echo "FINISHED"; + /sbin/m5 exit + + return +} + +wait_bb_finishfifo() { + echo "FINISH

FINISH

" > /data/bbench/finish_fifo.html + + return +} + +mkfifo_bbench() { + mkfifo /data/bbench/finish_fifo.html + + return +} + +run_bbench_test() { + echo "STARTING BBENCH" + + mkfifo_bbench + + am start -n com.android.browser/.BrowserActivity + wait_bb_finishfifo + + echo "END OF BBENCH RUN" + + rm /data/bbench/finish_fifo.html + stop_m5 + + return +} + +sleep 10 +/sbin/m5 dumpstats +/sbin/m5 resetstats +run_bbench_test diff --git a/simulators/gem5/configs/boot/bn-app.rcS b/simulators/gem5/configs/boot/bn-app.rcS new file mode 100644 index 00000000..6fe2800f --- /dev/null +++ b/simulators/gem5/configs/boot/bn-app.rcS @@ -0,0 +1,3 @@ +cd /benchmarks/bn +./bottleneck-app +m5 exit diff --git a/simulators/gem5/configs/boot/bonnie.rcS b/simulators/gem5/configs/boot/bonnie.rcS new file mode 100644 index 00000000..65b2fd6c --- /dev/null +++ b/simulators/gem5/configs/boot/bonnie.rcS @@ -0,0 +1,13 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "Mounting empty disk..." +mkdir /tmp-space +/bin/mount /dev/hdb1 /tmp-space +chmod a+rwx /tmp-space +echo "done." + +/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /tmp-space +m5 exit diff --git a/simulators/gem5/configs/boot/bonnie.symbol b/simulators/gem5/configs/boot/bonnie.symbol new file mode 100644 index 00000000..041753eb --- /dev/null +++ b/simulators/gem5/configs/boot/bonnie.symbol @@ -0,0 +1,309 @@ +0000000120025cb0 V DW.ref._ZTISt9bad_alloc +0000000120025c98 V DW.ref.__gxx_personality_v0 +0000000120025018 D _DYNAMIC +00000001200255a0 D _GLOBAL_OFFSET_TABLE_ +0000000120025c80 G _IO_stdin_used +00000001200251e0 T _PROCEDURE_LINKAGE_TABLE_ +000000012000e8a0 T _Unwind_Backtrace +000000012000e860 T _Unwind_DeleteException +000000012000c290 T _Unwind_FindEnclosingFunction +0000000120010df0 T _Unwind_Find_FDE +0000000120010850 t _Unwind_Find_registered_FDE +000000012000e470 T _Unwind_ForcedUnwind +000000012000e340 t _Unwind_ForcedUnwind_Phase2 +000000012000c260 T _Unwind_GetCFA +000000012000c2d0 T _Unwind_GetDataRelBase +000000012000e9d0 T _Unwind_GetGR +000000012000e9f0 T _Unwind_GetIP +000000012000c270 T _Unwind_GetLanguageSpecificData +000000012000c280 T _Unwind_GetRegionStart +000000012000c2e0 T _Unwind_GetTextRelBase +0000000120010ac0 t _Unwind_IteratePhdrCallback +000000012000e160 T _Unwind_RaiseException +000000012000e070 t _Unwind_RaiseException_Phase2 +000000012000e5c0 T _Unwind_Resume +000000012000e710 T _Unwind_Resume_or_Rethrow +000000012000e9e0 T _Unwind_SetGR +000000012000ea00 T _Unwind_SetIP +0000000120003cb0 T _Z10TestDirOpsiiiiR12CGlobalItems +0000000120003220 T _Z11TestFileOpsiR12CGlobalItems +0000000120009250 T _Z11bon_setugidPKcS0_b +00000001200096b4 t _Z12read_sleb128PKhPl +0000000120009678 t _Z12read_uleb128PKhPm +0000000120009a04 t _Z15get_ttype_entryP16lsda_header_infom +0000000120009a84 t _Z16get_adjusted_ptrPKSt9type_infoS1_PPv +000000012000ab40 t _Z16get_globals_dtorPv +000000012000ab9c t _Z16get_globals_initv +00000001200098a8 t _Z17parse_lsda_headerP15_Unwind_ContextPKhP16lsda_header_info +0000000120009b30 t _Z20check_exception_specP16lsda_header_infoPKSt9type_infoPvl +0000000120009be0 t _Z20empty_exception_specP16lsda_header_infol +00000001200095b4 t _Z21base_of_encoded_valuehP15_Unwind_Context +000000012000abe0 t _Z21get_globals_init_oncev +0000000120009548 t _Z21size_of_encoded_valueh +000000012000a3ec t _Z23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception +000000012000970c t _Z28read_encoded_value_with_basehmPKhPm +0000000120004200 T _Z5usagev +0000000120004510 T _Z6seekerP4ForkPvi +0000000120004240 T _Z8io_errorPKcb +000000012000a310 T _ZN10__cxxabiv111__terminateEPFvvE +000000012000a374 T _ZN10__cxxabiv112__unexpectedEPFvvE +000000012000b08c T _ZN10__cxxabiv117__class_type_infoD0Ev +000000012000b058 T _ZN10__cxxabiv117__class_type_infoD1Ev +000000012000b024 T _ZN10__cxxabiv117__class_type_infoD2Ev +0000000120025ca0 G _ZN10__cxxabiv119__terminate_handlerE +000000012000b148 T _ZN10__cxxabiv120__si_class_type_infoD0Ev +000000012000b114 T _ZN10__cxxabiv120__si_class_type_infoD1Ev +000000012000b0e0 T _ZN10__cxxabiv120__si_class_type_infoD2Ev +0000000120025ca8 G _ZN10__cxxabiv120__unexpected_handlerE +000000012000b204 T _ZN10__cxxabiv121__vmi_class_type_infoD0Ev +000000012000b1d0 T _ZN10__cxxabiv121__vmi_class_type_infoD1Ev +000000012000b19c T _ZN10__cxxabiv121__vmi_class_type_infoD2Ev +00000001200024b0 T _ZN12CGlobalItems18decrement_and_waitEi +0000000120002380 T _ZN12CGlobalItemsC1EPb +0000000120002250 T _ZN12CGlobalItemsC2EPb +0000000120008de0 T _ZN4Fork2goEPFvPS_PviES1_i +0000000120009080 T _ZN4Fork4ReadEPvii +0000000120009010 T _ZN4Fork4waitEv +0000000120009160 T _ZN4Fork5WriteEPvii +0000000120008d60 T _ZN4Fork7startitEP11THREAD_DATA +0000000120008d40 T _ZN4ForkC1Ev +0000000120008d20 T _ZN4ForkC2Ev +0000000120004cd0 T _ZN7CFileOp10read_blockEPv +0000000120004f90 T _ZN7CFileOp11write_blockEPv +0000000120004e70 T _ZN7CFileOp15read_block_getcEPc +0000000120005080 T _ZN7CFileOp16write_block_putcEv +0000000120005180 T _ZN7CFileOp4openEPKcbb +0000000120004a40 T _ZN7CFileOp4seekEii +0000000120005770 T _ZN7CFileOp5closeEv +0000000120005910 T _ZN7CFileOp6doseekElb +0000000120005630 T _ZN7CFileOp6m_openEPKcib +0000000120005430 T _ZN7CFileOp6reopenEbb +0000000120004760 T _ZN7CFileOp9seek_testEbR9Semaphore +0000000120005330 T _ZN7CFileOpC1ER8BonTimeriib +0000000120005230 T _ZN7CFileOpC2ER8BonTimeriib +0000000120004400 T _ZN7CFileOpD1Ev +00000001200042f0 T _ZN7CFileOpD2Ev +0000000120007b40 T _ZN8BonTimer10InitializeEv +0000000120007820 T _ZN8BonTimer10cpu_so_farEv +0000000120007c80 T _ZN8BonTimer10print_statE7tests_t +0000000120007f80 T _ZN8BonTimer11PrintHeaderEP8_IO_FILE +00000001200078f0 T _ZN8BonTimer11get_cpu_useEv +0000000120007970 T _ZN8BonTimer11get_delta_tE7tests_t +00000001200077e0 T _ZN8BonTimer11time_so_farEv +0000000120007860 T _ZN8BonTimer12get_cur_timeEv +0000000120007b70 T _ZN8BonTimer14print_cpu_statE7tests_t +0000000120007e40 T _ZN8BonTimer15print_file_statE7tests_t +0000000120007a10 T _ZN8BonTimer16add_delta_reportER8report_s7tests_t +00000001200079c0 T _ZN8BonTimer16get_delta_reportER8report_s +0000000120008030 T _ZN8BonTimer8DoReportEPKciiiiiiP8_IO_FILE +0000000120007790 T _ZN8BonTimer9timestampEv +0000000120007b00 T _ZN8BonTimerC1Ev +0000000120007ac0 T _ZN8BonTimerC2Ev +00000001200061a0 T _ZN9COpenTest10make_namesEb +0000000120005bf0 T _ZN9COpenTest11random_sortEv +0000000120007400 T _ZN9COpenTest11stat_randomER8BonTimer +0000000120006520 T _ZN9COpenTest13create_a_fileEPKcPcii +0000000120006710 T _ZN9COpenTest13create_a_linkEPKcS1_i +0000000120006c50 T _ZN9COpenTest13delete_randomER8BonTimer +00000001200074c0 T _ZN9COpenTest15stat_sequentialER8BonTimer +0000000120006f10 T _ZN9COpenTest17delete_sequentialER8BonTimer +0000000120006830 T _ZN9COpenTest6createEPKcR8BonTimeriiiib +0000000120007280 T _ZN9COpenTest9stat_fileEPKc +0000000120005b50 T _ZN9COpenTestC1EibPb +0000000120005ab0 T _ZN9COpenTestC2EibPb +0000000120005f40 T _ZN9COpenTestD1Ev +0000000120005ce0 T _ZN9COpenTestD2Ev +0000000120008aa0 T _ZN9Semaphore18decrement_and_waitEi +0000000120008920 T _ZN9Semaphore6createEi +0000000120008850 T _ZN9Semaphore9clear_semEv +0000000120008be0 T _ZN9Semaphore9get_mutexEv +0000000120008a10 T _ZN9Semaphore9get_semidEv +0000000120008c80 T _ZN9Semaphore9put_mutexEv +00000001200087d0 T _ZN9SemaphoreC1Eiii +0000000120008750 T _ZN9SemaphoreC2Eiii +000000012000b258 T _ZNK10__cxxabiv117__class_type_info10__do_catchEPKSt9type_infoPPvj +000000012000ba74 T _ZNK10__cxxabiv117__class_type_info11__do_upcastEPKS0_PKvRNS0_15__upcast_resultE +000000012000b2b8 T _ZNK10__cxxabiv117__class_type_info11__do_upcastEPKS0_PPv +000000012000b4c0 T _ZNK10__cxxabiv117__class_type_info12__do_dyncastElNS0_10__sub_kindEPKS0_PKvS3_S5_RNS0_16__dyncast_resultE +000000012000b330 T _ZNK10__cxxabiv117__class_type_info20__do_find_public_srcElPKvPKS0_S2_ +000000012000baa4 T _ZNK10__cxxabiv120__si_class_type_info11__do_upcastEPKNS_17__class_type_infoEPKvRNS1_15__upcast_resultE +000000012000b510 T _ZNK10__cxxabiv120__si_class_type_info12__do_dyncastElNS_17__class_type_info10__sub_kindEPKS1_PKvS4_S6_RNS1_16__dyncast_resultE +000000012000b340 T _ZNK10__cxxabiv120__si_class_type_info20__do_find_public_srcElPKvPKNS_17__class_type_infoES2_ +000000012000bb38 T _ZNK10__cxxabiv121__vmi_class_type_info11__do_upcastEPKNS_17__class_type_infoEPKvRNS1_15__upcast_resultE +000000012000b5c4 T _ZNK10__cxxabiv121__vmi_class_type_info12__do_dyncastElNS_17__class_type_info10__sub_kindEPKS1_PKvS4_S6_RNS1_16__dyncast_resultE +000000012000b394 T _ZNK10__cxxabiv121__vmi_class_type_info20__do_find_public_srcElPKvPKNS_17__class_type_infoES2_ +000000012000ab30 T _ZNKSt9exception4whatEv +000000012000b00c T _ZNKSt9type_info10__do_catchEPKS_PPvj +000000012000b01c T _ZNKSt9type_info11__do_upcastEPKN10__cxxabiv117__class_type_infoEPPv +000000012000affc T _ZNKSt9type_info14__is_pointer_pEv +000000012000b004 T _ZNKSt9type_info15__is_function_pEv +000000012000afa8 T _ZNSt10bad_typeidD0Ev +000000012000af74 T _ZNSt10bad_typeidD1Ev +000000012000af40 T _ZNSt10bad_typeidD2Ev +000000012000aadc T _ZNSt13bad_exceptionD0Ev +000000012000aaa8 T _ZNSt13bad_exceptionD1Ev +000000012000aa74 T _ZNSt13bad_exceptionD2Ev +000000012000aeec T _ZNSt8bad_castD0Ev +000000012000aeb8 T _ZNSt8bad_castD1Ev +000000012000ae84 T _ZNSt8bad_castD2Ev +000000012000add4 T _ZNSt9bad_allocD0Ev +000000012000ada0 T _ZNSt9bad_allocD1Ev +000000012000ad6c T _ZNSt9bad_allocD2Ev +000000012000aa40 T _ZNSt9exceptionD0Ev +000000012000aa2c T _ZNSt9exceptionD1Ev +000000012000aa18 T _ZNSt9exceptionD2Ev +000000012000ae50 T _ZNSt9type_infoD0Ev +000000012000ae3c T _ZNSt9type_infoD1Ev +000000012000ae28 T _ZNSt9type_infoD2Ev +000000012000a39c T _ZSt10unexpectedv +000000012000a3bc T _ZSt13set_terminatePFvvE +000000012000a3d4 T _ZSt14set_unexpectedPFvvE +000000012000ad54 T _ZSt15set_new_handlerPFvvE +000000012000a9e4 T _ZSt18uncaught_exceptionv +0000000120025cd0 G _ZSt7nothrow +000000012000a354 T _ZSt9terminatev +00000001200127d8 V _ZTIN10__cxxabiv117__class_type_infoE +00000001200127f0 V _ZTIN10__cxxabiv120__si_class_type_infoE +0000000120012808 V _ZTIN10__cxxabiv121__vmi_class_type_infoE +00000001200127c0 V _ZTISt10bad_typeid +0000000120012578 V _ZTISt13bad_exception +00000001200127a8 V _ZTISt8bad_cast +00000001200125d8 V _ZTISt9bad_alloc +0000000120012568 V _ZTISt9exception +0000000120012798 V _ZTISt9type_info +000000012001286b V _ZTSN10__cxxabiv117__class_type_infoE +0000000120012846 V _ZTSN10__cxxabiv120__si_class_type_infoE +0000000120012820 V _ZTSN10__cxxabiv121__vmi_class_type_infoE +000000012001288d V _ZTSSt10bad_typeid +0000000120012590 V _ZTSSt13bad_exception +000000012001289c V _ZTSSt8bad_cast +00000001200125f0 V _ZTSSt9bad_alloc +00000001200125a2 V _ZTSSt9exception +00000001200128a8 V _ZTSSt9type_info +00000001200126b0 V _ZTVN10__cxxabiv117__class_type_infoE +0000000120012658 V _ZTVN10__cxxabiv120__si_class_type_infoE +0000000120012600 V _ZTVN10__cxxabiv121__vmi_class_type_infoE +0000000120012708 V _ZTVSt10bad_typeid +0000000120012518 V _ZTVSt13bad_exception +0000000120012730 V _ZTVSt8bad_cast +00000001200125b0 V _ZTVSt9bad_alloc +0000000120012540 V _ZTVSt9exception +0000000120012758 V _ZTVSt9type_info +0000000120025cb8 g _ZZ18__gthread_active_pvE20__gthread_active_ptr +0000000120025cc8 g _ZZ18__gthread_active_pvE20__gthread_active_ptr +0000000120025cc4 g _ZZ21get_globals_init_oncevE4once +0000000120009518 T _ZdlPv +000000012000a648 T _Znam +000000012000a580 T _Znwm +00000001200251c0 d __CTOR_END__ +00000001200251b8 d __CTOR_LIST__ +00000001200251d0 d __DTOR_END__ +00000001200251c8 d __DTOR_LIST__ +0000000120024f30 r __FRAME_END__ +00000001200251d8 d __JCR_END__ +00000001200251d8 d __JCR_LIST__ +0000000120025ce8 A __bss_start +000000012000a694 T __cxa_allocate_exception +000000012000a884 T __cxa_begin_catch +000000012000a19c T __cxa_call_unexpected +000000012000a930 T __cxa_end_catch +000000012000a7b4 T __cxa_free_exception +000000012000ac84 T __cxa_get_globals +000000012000ac3c T __cxa_get_globals_fast +000000012000a4f8 T __cxa_rethrow +000000012000a45c T __cxa_throw +0000000120024000 D __data_start +000000012000fa50 T __deregister_frame +000000012000fa20 T __deregister_frame_info +000000012000f8c0 T __deregister_frame_info_bases +0000000120011470 t __do_global_ctors_aux +0000000120002160 t __do_global_dtors_aux +0000000120025c88 G __dso_handle +000000012000bd74 T __dynamic_cast +0000000120024000 A __fini_array_end +0000000120024000 A __fini_array_start +000000012000d250 T __frame_state_for +0000000120025ce0 g __gthread_active_ptr.0 +0000000120025cd8 g __gthread_active_ptr.1 +0000000120009c28 T __gxx_personality_v0 +0000000120024000 A __init_array_end +0000000120024000 A __init_array_start +00000001200113e0 T __libc_csu_fini +0000000120011350 T __libc_csu_init +0000000120025d00 S __new_handler +000000012000f6f0 T __register_frame +000000012000f6b0 T __register_frame_info +000000012000f5f0 T __register_frame_info_bases +000000012000f820 T __register_frame_info_table +000000012000f760 T __register_frame_info_table_bases +000000012000f860 T __register_frame_table +0000000120002120 W __start +0000000120025ce8 A _edata +0000000120035db0 A _end +00000001200114d0 T _fini +00000001200020b0 T _init +0000000120002120 T _start +0000000120010250 t add_fdes +0000000120025cea s already_printed_error +00000001200094b0 T arm +0000000120010a30 t base_from_cb_data +000000012000fab0 t base_from_object +000000012000bf50 t base_of_encoded_value +00000001200094f8 T checkpoint +00000001200100e0 t classify_object_over_fdes +0000000120025ce8 s completed.1 +00000001200024f0 T ctrl_c_handler +0000000120024000 W data_start +0000000120009508 T debugbreak +00000001200094e8 T dump_stats +00000001200094f0 T dumpreset_stats +0000000120035d40 b dwarf_reg_size_table +0000000120025d30 b emergency_buffer +0000000120024008 d emergency_mutex +0000000120025cf0 s emergency_used +000000012000caa0 t execute_cfa_program +000000012000c520 t execute_stack_op +0000000120025ce9 s exitNow +000000012000c2f0 t extract_cie_info +000000012000fd20 t fde_mixed_encoding_compare +000000012000fc60 t fde_single_encoding_compare +00000001200111d0 t fde_split +000000012000fc30 t fde_unencoded_compare +0000000120002200 t frame_dummy +000000012000fe00 t frame_heapsort +000000012000fb40 t get_cie_encoding +0000000120025cf8 s globals_key +0000000120035d30 b globals_static +000000012000ea10 t init_dwarf_reg_size_table +0000000120010e90 t init_object +00000001200094d8 T initparam +00000001200094c0 T ivlb +00000001200094c8 T ivle +00000001200103d0 t linear_search_fdes +00000001200094d0 T m5exit +0000000120002590 T main +0000000120025d10 s marker.1 +0000000120035d88 b object_mutex +0000000120025d08 s once_regsizes.0 +0000000120025c90 g p.0 +00000001200094b8 T quiesce +000000012000c0d0 t read_encoded_value_with_base +000000012000f460 t read_encoded_value_with_base +000000012000c060 t read_sleb128 +000000012000f3f0 t read_sleb128 +000000012000c020 t read_uleb128 +000000012000f3b0 t read_uleb128 +0000000120009500 T readfile +00000001200094e0 T reset_stats +0000000120010560 t search_object +0000000120025d20 s seen_objects +000000012000bed0 t size_of_encoded_value +000000012000f330 t size_of_encoded_value +0000000120009510 T switchcpu +0000000120025d18 s unseen_objects +0000000120025cc0 g use_thread_key +000000012000cf90 t uw_frame_state_for +000000012000d590 t uw_init_context_1 +000000012000d650 t uw_install_context_1 +000000012000d540 t uw_update_context +000000012000d390 t uw_update_context_1 diff --git a/simulators/gem5/configs/boot/bzip.rcS b/simulators/gem5/configs/boot/bzip.rcS new file mode 100644 index 00000000..369659ca --- /dev/null +++ b/simulators/gem5/configs/boot/bzip.rcS @@ -0,0 +1,6 @@ +#!/bin/sh + +cd /benchmarks/spec/bzip200/ +/sbin/m5 resetstats +/benchmarks/spec/bzip200/bzip2 lgred.graphic 1 +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/cc1.symbol b/simulators/gem5/configs/boot/cc1.symbol new file mode 100644 index 00000000..16c16912 --- /dev/null +++ b/simulators/gem5/configs/boot/cc1.symbol @@ -0,0 +1,3454 @@ +00000001201fec60 G DFbignan +00000001201fec68 G DFlittlenan +0000000120006f30 T GNU_xref_begin +0000000120006f70 T GNU_xref_end +00000001201e9b60 d Reg_names +00000001201fec70 G SFbignan +00000001201fec74 G SFlittlenan +00000001201e9ff8 D TFbignan +00000001201ea008 D TFlittlenan +00000001201e82c8 D W_options +00000001201ea018 D XFbignan +00000001201ea024 D XFlittlenan +00000001201fad48 D _DYNAMIC +00000001201fb210 D _GLOBAL_OFFSET_TABLE_ +00000001201febe8 G _IO_stdin_used +00000001201faf10 T _PROCEDURE_LINKAGE_TABLE_ +00000001201faef0 d __CTOR_END__ +00000001201faee8 d __CTOR_LIST__ +00000001201faf00 d __DTOR_END__ +00000001201faef8 d __DTOR_LIST__ +00000001201fad44 r __FRAME_END__ +00000001201faf08 d __JCR_END__ +00000001201faf08 d __JCR_LIST__ +00000001201fecdc A __bss_start +00000001201e6a58 D __data_start +000000012019eb20 t __do_global_ctors_aux +00000001200019e0 t __do_global_dtors_aux +00000001201febf0 G __dso_handle +00000001201e6a58 A __fini_array_end +00000001201e6a58 A __fini_array_start +00000001201e6a58 A __init_array_end +00000001201e6a58 A __init_array_start +000000012019ea80 T __libc_csu_fini +000000012019e9d0 T __libc_csu_init +00000001200019a0 W __start +00000001201fecdc A _edata +00000001202157c8 A _end +000000012019eb80 T _fini +0000000120001938 T _init +00000001200019a0 T _start +00000001202003e8 S abs_optab +00000001200d89c0 t abstract_origin_attribute +000000012016a550 t actual_hazard +000000012016af00 t actual_hazard_this_instance +000000012016fb20 t add_bb_string +00000001201831a0 T add_clobbers +00000001201ff138 s add_cost +0000000120200858 S add_cost +0000000120164b10 t add_dependence +0000000120055d40 T add_double +00000001200b4c60 T add_insn +00000001200b2c40 T add_insn_after +00000001200b2d90 T add_insn_before +000000012002f860 t add_ixpansion +00000001200fed90 t add_label_notes +0000000120197770 T add_operand +0000000120200408 S add_optab +000000012015d210 t add_to_delay_list +00000001201ff5f8 s added_links_insn +00000001201ff4c0 s addr_combined_regs +00000001201ff4b8 s addr_placeholder +00000001201731d0 T address_operand +00000001201720f0 T adj_offsettable_operand +00000001200dfe00 t adjust_copied_decl_tree +000000012016aa30 t adjust_priority +0000000120095b20 T adjust_stack +00000001200291a0 t affix_data_type +00000001201ff588 s after_insn_hard_regs +0000000120062e10 T aggregate_value_p +00000001201fed48 s align.4 +000000012005f550 t all_blocks +000000012006a350 T all_cases_count +00000001201eb418 d all_from_align +00000001201ff3e8 s all_minus_one +0000000120200110 S all_types_permanent +0000000120134ef0 t alloc_qty_for_scratch +0000000120094f90 T allocate_dynamic_stack_space +000000012010fc50 T allocate_for_life_analysis +0000000120154180 t allocate_reload_reg +00000001200422b0 T allocation_temporary_p +00000001201ff808 s allocno_calls_crossed +000000012013a160 t allocno_compare +00000001201ff818 s allocno_live_length +00000001201ff810 s allocno_n_refs +00000001201ff7a0 s allocno_order +00000001201ff798 s allocno_reg +00000001201ff7c0 s allocno_row_words +00000001201ff7a8 s allocno_size +00000001201ff820 s allocnos_live +00000001201fed6c s already.0 +00000001201ff698 s altclass +000000012014b230 t alter_reg +000000012016e1e0 T alter_subreg +0000000120140e20 t alternative_allows_memconst +0000000120190fb0 t alu_unit_blockage +000000012018cc20 T alu_unit_blockage_range +000000012018c790 T alu_unit_ready_cost +00000001202005d8 S and_optab +00000001200387d0 T announce_function +00000001201ff258 s anonymous_types +0000000120095bd0 T anti_adjust_stack +00000001201645f0 T anti_dependence +000000012006f4f0 T any_pending_cleanups +000000012016f6b0 T app_disable +000000012016f690 T app_enable +00000001201ffb1c s app_on +0000000120203548 b apply_args_mode +0000000120203748 b apply_args_reg_offset +0000000120082a30 T apply_args_register_offset +0000000120084640 t apply_args_size +00000001201ff108 s apply_args_value +000000012016fd70 T apply_change_group +0000000120122f00 t apply_distributive_law +0000000120203648 b apply_result_mode +0000000120084920 t apply_result_size +000000012010d890 t approx_final_value +00000001202007d8 S arg_pointer_rtx +00000001202001e8 S arg_pointer_save_area +00000001201e73ff d argnofun.1 +00000001201e73e8 d argstring.0 +0000000120197640 T arith32_operand +00000001201975c0 T arith5_operand +00000001201976b0 T arith64_operand +0000000120197540 T arith_operand +00000001201eb6b8 d arityvec +0000000120043af0 T array_type_nelts +00000001200ba350 t asctoe +00000001200ba340 t asctoe113 +00000001200ba310 t asctoe24 +00000001200ba320 t asctoe53 +00000001200ba330 t asctoe64 +00000001200ba360 t asctoeg +00000001202004f0 S ashl_optab +0000000120200608 S ashr_optab +00000001201fff10 S asm_file_name +000000012016f110 T asm_fprintf +000000012016c9c0 t asm_insn_count +0000000120171ab0 T asm_noperands +0000000120200058 S asm_out_file +00000001200a80b0 T assemble_alias +00000001200a8fb0 T assemble_align +00000001200a8b20 T assemble_asm +00000001200a8a10 T assemble_constant_align +00000001200a8cb0 T assemble_constructor +00000001200a8bd0 T assemble_destructor +00000001200a8dd0 T assemble_end_function +00000001200a9310 T assemble_external +00000001200a9320 T assemble_external_libcall +00000001200a8d40 T assemble_gc_entry +00000001200a9330 T assemble_global +00000001200a4660 T assemble_integer +00000001200a93b0 T assemble_label +00000001200a3d40 T assemble_name +00000001200a4890 T assemble_real +00000001200a2700 T assemble_start_function +00000001200a3e80 T assemble_static_space +00000001200a9060 T assemble_string +00000001200a40f0 T assemble_trampoline_template +00000001200a2be0 T assemble_variable +00000001200a8f30 T assemble_zeros +0000000120059c00 T assign_outer_stack_local +000000012005d300 T assign_parms +0000000120059a60 T assign_stack_local +0000000120059db0 T assign_stack_temp +00000001201e7368 d asso_values.0 +0000000120162c10 t attach_deaths +0000000120169c10 t attach_deaths_insn +0000000120040b10 T attribute_hash_list +0000000120040bc0 T attribute_list_contained +0000000120040b40 T attribute_list_equal +0000000120200b10 b attrtab +00000001201feec8 s attrtab_idx +0000000120200000 S aux_info_file +00000001201fefe0 s aux_info_file_name +000000012010cd40 T back_branch_in_range_p +00000001201ff8a4 s bad_spill_regs +000000012006c730 t balance_case_nodes +00000001201ff218 s base_label_num +00000001201ff520 s basic_block_drops_in +00000001202008c8 S basic_block_end +00000001202008d8 S basic_block_head +0000000120200878 S basic_block_live_at_start +00000001201ff528 s basic_block_loop_depth +0000000120215098 B basic_block_needs +00000001201045b0 t basic_induction_var +00000001201ffa18 s bb_dead_regs +00000001201fecb8 g bb_file_label_num +00000001201fecbc g bb_func_label_num +00000001201ffad0 s bb_head +00000001201ffa20 s bb_live_regs +00000001201fecb0 g bb_tail +00000001201ff968 s bb_ticks +0000000120081f90 T bc_adjust_stack +000000012019c610 T bc_align +000000012019b890 T bc_align_bytecode +000000012019bd00 T bc_align_const +000000012019bfa0 T bc_align_data +00000001200810f0 T bc_allocate_local +0000000120082af0 T bc_allocate_variable_array +000000012019b760 T bc_begin_function +0000000120063420 T bc_build_calldesc +0000000120081320 T bc_canonicalize_array_ref +000000012006ab50 t bc_check_for_full_enumeration_handling +000000012019c5f0 T bc_data +00000001201ffbc8 s bc_data_seg +000000012019b710 T bc_define_pointer +000000012019c760 T bc_emit +000000012019cb00 T bc_emit_bytecode +000000012019b960 T bc_emit_bytecode_const +000000012019ba90 T bc_emit_bytecode_labeldef +000000012019bb10 T bc_emit_bytecode_labelref +000000012019bc00 T bc_emit_code_labelref +000000012019c240 T bc_emit_common +000000012019bdd0 T bc_emit_const +000000012019bf60 T bc_emit_const_labeldef +000000012019bf80 T bc_emit_const_labelref +000000012019bea0 T bc_emit_const_skip +000000012019c070 T bc_emit_data +000000012019c200 T bc_emit_data_labeldef +000000012019c220 T bc_emit_data_labelref +000000012019c140 T bc_emit_data_skip +000000012019ac10 T bc_emit_instruction +000000012019c9b0 T bc_emit_labeldef +000000012019ca00 T bc_emit_labelref +000000012019c890 T bc_emit_skip +000000012019cc40 T bc_emit_trampoline +000000012019a140 T bc_end_function +0000000120081600 T bc_expand_address +000000012019d430 T bc_expand_binary_operation +0000000120081480 T bc_expand_component_address +0000000120081a90 T bc_expand_constructor +000000012019dd40 T bc_expand_conversion +0000000120068a10 t bc_expand_decl +0000000120068ce0 t bc_expand_decl_init +0000000120068110 t bc_expand_end_bindings +000000012006bc60 t bc_expand_end_case +0000000120065b50 t bc_expand_end_cond +000000012006fc40 t bc_expand_end_loop +000000012007b490 T bc_expand_expr +0000000120064180 t bc_expand_fixup +0000000120063670 T bc_expand_function_end +000000012005fcc0 T bc_expand_function_start +000000012006f690 t bc_expand_goto_internal +000000012019df90 T bc_expand_increment +0000000120069450 t bc_expand_start_case +0000000120065ab0 t bc_expand_start_cond +000000012019de90 T bc_expand_truth_conversion +000000012019d900 T bc_expand_unary_operation +0000000120064240 t bc_fixup_gotos +0000000120081910 T bc_gen_constr_label +000000012019ca60 T bc_gen_rtx +000000012019ba30 T bc_get_bytecode_label +000000012019c420 T bc_globalize_label +000000012019d350 T bc_init_mode_to_code_map +000000012006fe00 T bc_init_mode_to_opcode_maps +0000000120199ef0 T bc_initialize +0000000120082b60 T bc_load_bit_field +00000001200811a0 T bc_load_externaddr +0000000120081200 T bc_load_externaddr_id +0000000120081290 T bc_load_localaddr +0000000120080f90 T bc_load_memory +00000001200812d0 T bc_load_parmaddr +00000001200a9d10 t bc_make_decl_rtl +000000012006f5a0 T bc_new_uid +00000001200a9160 T bc_output_constructor +00000001200a9250 T bc_output_data_constructor +000000012019caf0 T bc_print_rtl +00000001200815a0 T bc_push_offset_and_size +000000012006a050 t bc_pushcase +0000000120081870 T bc_runtime_type_code +0000000120081f50 T bc_store_bit_field +0000000120081e50 T bc_store_field +0000000120081040 T bc_store_memory +000000012019c5d0 T bc_text +00000001201ffbc0 s bc_text_seg +00000001201ff0b0 s bc_uid.1 +000000012019ca50 T bc_write_file +000000012019ce50 T bc_xstrdup +000000012020c108 B bcc_gen_fctn +00000001202004d0 S bcmp_libfunc +0000000120200698 S bcopy_libfunc +00000001201eb43c d best_from_align +000000012002b5a0 T binary_op_error +0000000120043510 T binfo_member +000000012016add0 t birthing_insn_p +00000001200d8380 t bit_offset_attribute +000000012018ed90 T bit_unit_ready_cost +000000012010ce50 T biv_total_increment +0000000120132150 t block_alloc +00000001201ffb18 s block_depth +00000001201ff530 s block_live_static +0000000120198b80 t block_move_loop +0000000120191ea0 t block_move_no_loop +00000001201921e0 t block_move_sequence +00000001202002d0 S block_stack +00000001202002ac S block_start_count +00000001201ff0e8 s block_vector +000000012005f520 t blocks_nreverse +00000001201e9f94 d bmask +00000001201ffda0 S boolean_false_node +00000001201ffcc8 S boolean_true_node +00000001201ffe58 S boolean_type_node +0000000120038bb0 T botch +0000000120096150 t break_out_memory_refs +0000000120205fe4 b buffer.0 +0000000120206048 b buffer.1 +00000001202063cc b buffer.10 +0000000120206430 b buffer.11 +0000000120206494 b buffer.12 +00000001201fedf8 s buffer.2 +00000001202060ac b buffer.2 +0000000120206110 b buffer.3 +0000000120206174 b buffer.4 +00000001202061d8 b buffer.5 +000000012020623c b buffer.6 +00000001202062a0 b buffer.7 +0000000120206304 b buffer.8 +0000000120206368 b buffer.9 +00000001201feee0 s buffer_length.2 +000000012003fff0 T build +0000000120040250 T build1 +000000012001adb0 T build_array_ref +00000001200414f0 T build_array_type +000000012001c1a0 T build_binary_op +0000000120044230 T build_block +000000012001fc20 T build_c_cast +0000000120042a00 T build_complex +00000001200415e0 T build_complex_type +000000012001a930 T build_component_ref +00000001200255b0 T build_compound_expr +000000012001f570 T build_conditional_expr +0000000120044170 T build_decl +00000001200442b0 T build_decl_attribute_variant +00000001200437a0 T build_decl_list +0000000120014920 T build_enumerator +000000012001b260 T build_function_call +0000000120044ed0 T build_function_type +0000000120044dd0 T build_index_2_type +0000000120044c40 T build_index_type +000000012001abc0 T build_indirect_ref +00000001200427b0 T build_int_2_wide +0000000120045090 T build_method_type +0000000120020200 T build_modify_expr +00000001200403e0 T build_nt +0000000120006f10 T build_objc_string +0000000120045170 T build_offset_type +00000001200404a0 T build_parse_node +00000001200412a0 T build_pointer_type +00000001200413a0 T build_range_type +0000000120042800 T build_real +000000012003dc50 T build_real_from_int_cst +0000000120044fd0 T build_reference_type +000000012003e0c0 T build_string +0000000120043750 T build_tree_list +0000000120040590 T build_type_attribute_variant +0000000120040810 T build_type_copy +0000000120040740 T build_type_variant +000000012001e500 T build_unary_op +00000001200105e0 T builtin_function +00000001202006f4 S byte_mode +00000001200d81c0 t byte_size_attribute +0000000120200a28 S bytecode +0000000120200510 S bzero_libfunc +0000000120025510 T c_alignof +0000000120019fd0 T c_alignof_expr +000000012002d690 T c_build_type_variant +000000012000c410 T c_decode_option +0000000120024980 T c_expand_asm_operands +000000012002d190 T c_expand_expr_stmt +0000000120024c10 T c_expand_return +0000000120025bf0 T c_expand_start_case +00000001201ffc18 S c_function_chain +00000001201fedc0 s c_function_varargs +0000000120017a00 T c_mark_varargs +0000000120025430 T c_size_in_bytes +0000000120019e30 T c_sizeof +0000000120025350 T c_sizeof_nowarn +0000000120084500 t c_strlen +000000012010d100 t calculate_giv_inc +0000000120197400 T call_address_operand +0000000120200928 S call_fixed_reg_set +0000000120213ab0 B call_fixed_regs +0000000120200910 S call_used_reg_set +0000000120213a70 B call_used_regs +0000000120200978 S caller_save_needed +0000000120084d50 t calls_function_1 +00000001201ff128 s calls_function_save_exprs +000000012012c200 t can_combine_p +000000012009c7e0 T can_compare_p +00000001200a15b0 T can_extend_p +0000000120200800 S can_reach_end +00000001200e6860 T can_reverse_comparison_p +00000001201700e0 T cancel_changes +00000001201ff8c0 s cannot_omit_stores +00000001200e9090 t canon_hash +00000001200ea190 t canon_reg +00000001201648e0 t canon_rtx +000000012006f570 T case_index_expr_type +00000001202002c8 S case_stack +00000001201ff53c s cc0_live +0000000120200718 S cc0_rtx +00000001202007c8 S cc1_rtx +0000000120093200 T ceil_log2 +0000000120043540 T chain_member +00000001200435a0 T chain_member_purpose +0000000120043570 T chain_member_value +00000001200435f0 T chainon +00000001200b22f0 T change_address +0000000120209a58 b change_locs +0000000120044710 T change_main_variant +0000000120209800 b change_objects +0000000120209990 b change_old_codes +0000000120209be8 b change_olds +00000001201ffc30 S char_array_type_node +00000001201ffcb8 S char_type_node +000000012016fc40 T check_asm_operands +000000012002d290 T check_case_value +0000000120105f70 t check_dbra_loop +00000001201040a0 t check_final_value +000000012006a850 T check_for_full_enumeration_handling +000000012002d7a0 t check_format_info +000000012002cce0 T check_function_format +00000001200234d0 t check_init_type_bitfields +0000000120008020 T check_newline +000000012012ff00 T choose_hard_reg_mode +0000000120093540 t choose_multiplier +000000012014e7e0 t choose_reload_regs +0000000120213514 B class_narrowest_mode +00000001200b3080 T classify_insn +0000000120196810 T classify_integer +0000000120200240 S cleanup_label +00000001202002d8 S cleanups_this_call +0000000120200a40 b clear_binding_level +00000001200a9450 T clear_const_double_mem +000000012006e9f0 T clear_last_expr +0000000120042460 T clear_momentary +0000000120017050 T clear_parm_order +0000000120082a90 T clear_pending_stack_adjust +00000001201559d0 t clear_reg_live +0000000120153020 t clear_reload_reg_in_use +0000000120082650 T clear_storage +0000000120200358 S cmp_optab +000000012020c4a8 B code_to_optab +000000012002e9d0 t collect_iterators +0000000120114400 t combinable_i3pat +00000001201ff590 s combine_attempts +00000001201fef14 S combine_dump +00000001201ffef0 S combine_dump_file +00000001201ff598 s combine_extras +0000000120105650 t combine_givs +0000000120113b30 T combine_instructions +00000001201ff5bc s combine_max_regno +00000001201ff594 s combine_merges +00000001200fe3a0 t combine_movables +0000000120015c30 T combine_parm_decls +0000000120133580 t combine_regs +0000000120146c80 t combine_reloads +00000001200294d0 T combine_strings +00000001201ff59c s combine_successes +000000012005a0d0 T combine_temp_slots +00000001201fffd4 S combine_time +0000000120019070 T common_type +00000001200801f0 t compare +00000001200a5200 t compare_constant_1 +0000000120080310 T compare_from_rtx +0000000120152d50 t compare_spill_regs +00000001200e6bb0 T comparison_dominates_p +0000000120173a00 T comparison_operator +0000000120039530 t compile_file +00000001201feeb8 s compiled_from_record.0 +0000000120011560 T complete_array_type +00000001201fece0 s completed.1 +00000001201ffc08 S complex_double_type_node +00000001201ffe70 S complex_float_type_node +00000001201ffc38 S complex_integer_type_node +00000001201ffce8 S complex_long_double_type_node +00000001200196f0 T comptypes +0000000120200288 S cond_stack +00000001201968b0 T condition_value +00000001200e6db0 T condjump_in_parallel_p +00000001200e6cd0 T condjump_p +00000001201ff7b8 s conflicts +00000001201ff3f0 s consec_ints +0000000120105360 t consec_sets_giv +00000001201012d0 t consec_sets_invariant_p +0000000120200708 S const0_rtx +0000000120200780 S const1_rtx +0000000120200750 S const2_rtx +000000012004aac0 t const_binop +00000001201ff170 s const_double_chain +0000000120173400 T const_double_operand +00000001200a4df0 t const_hash +0000000120203b98 b const_hash_table +00000001201733f0 T const_int_operand +0000000120205b20 b const_int_rtx +00000001202006c8 S const_labelno +000000012018ee30 T const_num_delay_slots +00000001201ffe38 S const_ptr_type_node +00000001201ff188 s const_rtx_hash_table +00000001201ff1a8 s const_rtx_sym_hash_table +00000001200a8260 T const_section +00000001201ffe60 S const_string_type_node +0000000120213530 B const_tiny_rtx +00000001202007b8 S const_true_rtx +00000001200d9fa0 t const_value_attribute +000000012002cd30 T constant_expression_warning +00000001201ff438 s constant_pool_entries_cost +0000000120200798 S constm1_rtx +00000001201723a0 T constrain_operands +0000000120152980 t constraint_accepts_reg_p +00000001201feea0 s constructor_asmspec +00000001201fee58 s constructor_bit_index +00000001201fee68 s constructor_constant +00000001201fee98 s constructor_decl +00000001201fee80 s constructor_depth +00000001201fee60 s constructor_elements +00000001201fee70 s constructor_erroneous +00000001201fee28 s constructor_fields +00000001201fee84 s constructor_implicit +00000001201fee90 s constructor_incremental +00000001201fee30 s constructor_index +00000001201fee40 s constructor_max_index +00000001201fee00 S constructor_no_implicit +00000001201fee78 s constructor_pending_elts +00000001201fee38 s constructor_range_end +00000001201feeb0 s constructor_result +00000001201fee6c s constructor_simple +00000001201ffe98 S constructor_stack +00000001201fee74 s constructor_subconstants_deferred +00000001201feea8 s constructor_top_level +00000001201fee20 s constructor_type +00000001201fee48 s constructor_unfilled_fields +00000001201fee50 s constructor_unfilled_index +0000000120043f90 T contains_placeholder_p +00000001200a3c50 t contains_pointers_p +00000001201ff030 s context_display +00000001201ec720 d conversion_info +000000012019e5b0 t conversion_reasonable_p +000000012020ae90 b conversion_recipe +0000000120026880 T convert +000000012002cf90 T convert_and_check +000000012001b520 t convert_arguments +0000000120020650 t convert_for_assignment +0000000120071230 T convert_modes +0000000120070530 T convert_move +0000000120199c60 T convert_to_complex +0000000120199080 T convert_to_integer +00000001200711f0 T convert_to_mode +0000000120199930 T convert_to_pointer +0000000120199ad0 T convert_to_real +00000001200959e0 T copy_addr_to_reg +0000000120095600 T copy_all_regs +00000001201ff300 s copy_asm_constraints_vector +00000001201ff2f8 s copy_asm_operands_vector +00000001200a5dc0 t copy_constant +000000012012f480 t copy_cost +0000000120200834 S copy_cost +00000001200dae60 t copy_decl_list +00000001200dafd0 t copy_decl_rtls +00000001200daf10 t copy_decl_tree +00000001200db590 t copy_for_inline +0000000120017c10 T copy_lang_decl +00000001200426f0 T copy_list +0000000120109ac0 t copy_loop_body +00000001200aab70 T copy_most_rtx +000000012003d5b0 T copy_node +0000000120143780 T copy_replacements +00000001200aa7c0 T copy_rtx +00000001200dda30 T copy_rtx_and_substitute +00000001200b2430 T copy_rtx_if_shared +0000000120094b10 T copy_to_mode_reg +0000000120094a50 T copy_to_reg +0000000120095a90 T copy_to_suggested_reg +0000000120200440 S cos_optab +00000001201ff0d0 s cost_table +00000001201ff688 s costs +00000001201ffaf8 s count_basic_blocks +0000000120038620 T count_error +0000000120101550 t count_loop_regs_set +0000000120100050 t count_nonfixed_reads +0000000120152a80 t count_occurrences +000000012014a920 t count_possible_groups +00000001200f4b50 t count_reg_usage +00000001201ff8b0 s counted_for_groups +00000001201ff8b8 s counted_for_nongroups +0000000120165850 t create_reg_dead_note +00000001201ff310 s cross_jump_death_matters +00000001201fef0c S cse2_dump +00000001201fff38 S cse2_dump_file +00000001201fff90 S cse2_time +00000001200f4080 t cse_basic_block +00000001201ff3fc s cse_basic_block_end +00000001201ff3f8 s cse_basic_block_start +00000001200fc2e0 t cse_check_loop_start +00000001201ff440 s cse_check_loop_start_value +00000001201fef04 S cse_dump +00000001201ffff8 S cse_dump_file +00000001200f3530 T cse_end_of_basic_block +00000001200ed360 t cse_gen_binary +00000001200f6d90 t cse_insn +00000001201ff40c s cse_jumps_altered +00000001200f3a60 T cse_main +00000001202002e4 S cse_not_expected +00000001200f3290 t cse_process_notes +00000001200fb530 t cse_set_around_loop +00000001201fff44 S cse_time +00000001200a83f0 T ctors_section +00000001201fec54 g cur_insn_uid +00000001201fedd0 s current_binding_level +00000001201fed08 s current_declspecs +00000001201ff290 s current_dienum +00000001201fedc8 s current_extern_inline +00000001201fec90 g current_funcdef_number +0000000120200218 S current_function_arg_offset_rtx +0000000120200230 S current_function_args_info +0000000120200214 S current_function_args_size +0000000120200170 S current_function_calls_alloca +0000000120200188 S current_function_calls_longjmp +00000001202001a8 S current_function_calls_setjmp +0000000120200234 S current_function_contains_functions +00000001201ffd80 S current_function_decl +0000000120200168 S current_function_epilogue_delay_list +0000000120200258 S current_function_has_nonlocal_goto +0000000120200270 S current_function_has_nonlocal_label +00000001202001c8 S current_function_internal_arg_pointer +00000001202001f8 S current_function_name +0000000120200160 S current_function_needs_context +0000000120200248 S current_function_outgoing_args_size +00000001201fed98 s current_function_parm_tags +00000001201fed90 s current_function_parms +00000001202001c0 S current_function_pops_args +000000012020015c S current_function_pretend_args_size +00000001201feda0 s current_function_prototype_file +00000001201feda8 s current_function_prototype_line +0000000120200178 S current_function_return_rtx +00000001201ffcb0 S current_function_returns_null +0000000120200280 S current_function_returns_pcc_struct +0000000120200208 S current_function_returns_pointer +000000012020018c S current_function_returns_struct +00000001201ffdc0 S current_function_returns_value +00000001202001f0 S current_function_stdarg +0000000120200210 S current_function_uses_const_pool +00000001202001d0 S current_function_uses_pic_offset_table +000000012020020c S current_function_varargs +00000001201ff980 s current_live_regs +00000001202000a0 S current_obstack +00000001200d74c0 t data_member_location_attribute +00000001200a8580 T data_section +00000001201e6a58 W data_start +00000001201feec0 s data_type +00000001201fef2c S dbr_sched_dump +0000000120200038 S dbr_sched_dump_file +00000001201ffee0 S dbr_sched_time +00000001201593d0 T dbr_schedule +000000012016f6d0 T dbr_sequence_length +0000000120200730 S dconst0 +00000001202007d0 S dconst1 +0000000120200788 S dconst2 +0000000120200700 S dconstm1 +00000001201ffa30 s dead_notes +00000001200b08c0 T dead_or_set_p +00000001200ae500 T dead_or_set_regno_p +00000001201fef3c S debug_info_level +00000001201ffab8 s debug_insn +00000001201feffc S debug_no_type_hash +0000000120042380 T debug_obstack +00000001200bce10 T debug_real +0000000120145250 T debug_reload +00000001200acd80 T debug_rtx +00000001201ff1b8 S debug_rtx_count +00000001200acec0 T debug_rtx_find +00000001200acdd0 T debug_rtx_list +00000001201fec10 G debug_temp_inits +0000000120047750 T debug_tree +0000000120029800 T decl_attributes +0000000120041b90 T decl_function_context +0000000120039220 t decl_name +0000000120200060 S decl_printable_name +0000000120043810 T decl_tree_cons +00000001200453e0 T decl_type_context +000000012002c750 T declare_function_name +000000012006e810 T declare_nonlocal_label +0000000120016590 T declare_parm_level +00000001200a9b50 T declare_weak +00000001201fed10 s declspec_stack +00000001200a9f90 t decode_addr_const +0000000120171c90 T decode_asm_operands +0000000120058ce0 t decode_field_reference +00000001200a1bf0 T decode_reg_name +00000001200aa310 t decode_rtx_const +000000012013d160 t decompose +000000012019e060 t deduce_conversion +000000012001a1d0 T default_conversion +00000001201ffc48 S default_function_type +00000001200388a0 T default_print_error_function +00000001200a94a0 T defer_addressed_constants +00000001201ff180 s defer_addressed_constants_flag +000000012007e5d0 t defer_cleanups_to +00000001201ff178 s deferred_constants +000000012000e1a0 T define_label +0000000120016730 T delete_block +00000001200e4330 t delete_computation +00000001200f4de0 T delete_dead_from_cse +000000012014b150 t delete_dead_insn +00000001200e6f00 T delete_for_peephole +000000012015d2f0 t delete_from_delay_slot +00000001200e4d90 t delete_from_jump_chain +00000001200e4560 T delete_insn +00000001200b4ca0 T delete_insns_since +00000001200e42c0 T delete_jump +00000001200e5260 t delete_labelref_insn +0000000120152360 t delete_output_reload +0000000120021fc0 t digest_init +000000012020350c b direct_load +0000000120203529 b direct_store +00000001201feed8 s directive_buffer.1 +0000000120056e70 t distribute_bit_expr +000000012012ba90 t distribute_links +000000012012ad10 t distribute_notes +000000012004a2b0 T div_and_round_double +0000000120203a3c b div_cost +000000012018ee60 t div_unit_blockage +000000012018ebb0 T div_unit_blockage_range +000000012018b380 T div_unit_ready_cost +0000000120038b90 T do_abort +00000001201ff250 s do_block +00000001200e3700 t do_cross_jump +00000001201ff000 s do_identifier_warnings +000000012007e800 T do_jump +000000012007fc50 t do_jump_by_parts_equality +000000012007fe50 t do_jump_by_parts_equality_rtx +000000012007f710 t do_jump_by_parts_greater +000000012007f9e0 T do_jump_by_parts_greater_rtx +000000012007fff0 t do_jump_for_compare +000000012006c110 t do_jump_if_equal +00000001201ff414 s do_not_record +000000012007e550 T do_pending_stack_adjust +00000001201fec3c G do_preexpand_calls +0000000120080560 t do_store_flag +00000001201ffc00 S doing_objc_thang +00000001201fed68 S dollars_in_ident +00000001201ffd98 S double_ftype_double +00000001201ffe18 S double_ftype_double_double +0000000120200998 S double_reg_address_ok +00000001201ffd78 S double_type_node +000000012006f350 T drop_through_at_end_p +00000001200a8470 T dtors_section +0000000120200018 S dump_base_name +000000012012beb0 T dump_combine_stats +000000012012bf10 T dump_combine_total_stats +0000000120139930 t dump_conflicts +0000000120112190 T dump_flow_info +0000000120139f80 T dump_global_regs +0000000120134e20 T dump_local_alloc +00000001201fff6c S dump_time +00000001200454e0 T dump_tree_statistics +0000000120017c20 t duplicate_decls +00000001200e2ab0 t duplicate_loop_exit_test +00000001200ce060 t dwarf_attr_name +00000001200ce5e0 t dwarf_fund_type_name +00000001201ff2c0 s dwarf_last_decl +00000001200d7200 t dwarf_tag_name +00000001200cd250 T dwarfout_begin_block +00000001200cd480 T dwarfout_begin_function +00000001200cd900 T dwarfout_define +00000001200cd300 T dwarfout_end_block +00000001200cd5c0 T dwarfout_end_epilogue +00000001200cd520 T dwarfout_end_function +00000001200caa30 T dwarfout_file_scope_decl +00000001200cc540 T dwarfout_finish +00000001200cb950 T dwarfout_init +00000001200cd3b0 T dwarfout_label +00000001200cb160 T dwarfout_line +00000001200cd7c0 T dwarfout_resume_previous_source_file +00000001200cd650 T dwarfout_start_new_source_file +00000001200cdbb0 T dwarfout_undef +00000001201ff094 s dynamic_offset +00000001200b8a30 t e113toe +00000001200b8e80 t e24toe +00000001201e9e2c D e32 +00000001200b80a0 t e53toe +00000001200b8570 t e64toe +00000001200b6c40 t eadd +00000001200b6df0 t eadd1 +00000001200b65e0 T earith +000000012013c790 t earlyclobber_operand_p +00000001200b95e0 t ecmp +00000001200b7570 t ediv +00000001200bd6a0 t edivm +00000001200bc0d0 T efixi +00000001200bc140 T efixui +00000001200bb210 t efloor +00000001201e9e08 D ehalf +00000001200bea70 t eifrac +00000001200bb5c0 t eiremain +00000001200b6a30 t eisnan +00000001200b6a10 t eisneg +00000001200bb380 t eldexp +00000001200d84f0 t element_list_attribute +000000012018e7c0 T eligible_for_annul_true +000000012018e1b0 T eligible_for_delay +00000001201ff548 s elim_reg_set +00000001201e8fc8 d elim_regs.0 +00000001201ff834 s eliminable_regset +00000001201ea050 d eliminables.0 +00000001201ea0a0 d eliminables.0 +00000001201ea688 d eliminables.0 +00000001201ea670 d eliminables.2 +0000000120095380 T eliminate_constant_term +000000012014bc10 T eliminate_regs +000000012014cd40 t eliminate_regs_in_insn +00000001201e9e38 D elog2 +00000001200bdd70 t emdnorm +00000001200b5f30 T emit +00000001200a1250 T emit_0_to_1_insn +0000000120194ba0 t emit_add +00000001200b5be0 T emit_barrier +00000001200b3010 T emit_barrier_after +00000001200b5250 T emit_barrier_before +00000001201957a0 T emit_bcnd +0000000120071840 T emit_block_move +0000000120089a50 t emit_call_1 +00000001200b5ab0 T emit_call_insn +00000001200b5190 T emit_call_insn_before +000000012006cac0 t emit_case_nodes +00000001200a1210 T emit_clr_insn +000000012009c090 T emit_cmp_insn +000000012015cec0 t emit_delay_sequence +0000000120200298 S emit_filename +000000012009c830 T emit_float_lib_cmp +00000001200a1290 T emit_indirect_jump +00000001200b5750 T emit_insn +00000001200b2ee0 T emit_insn_after +00000001200b5340 T emit_insn_after_with_line_notes +00000001200b4fc0 T emit_insn_before +00000001200b58a0 T emit_insns +00000001200b5970 T emit_insns_after +00000001200b5900 T emit_insns_before +0000000120105ac0 T emit_iv_add_mult +000000012006e580 T emit_jump +000000012006ca30 t emit_jump_if_reachable +00000001200b59f0 T emit_jump_insn +00000001200b5500 T emit_jump_insn_after +00000001200b50e0 T emit_jump_insn_before +00000001200b5b80 T emit_label +00000001200b55b0 T emit_label_after +0000000120194ef0 t emit_ldst +000000012009be10 T emit_libcall_block +0000000120088070 T emit_library_call +00000001200887a0 T emit_library_call_value +00000001200b5c50 T emit_line_note +00000001200b5690 T emit_line_note_after +00000001200b5ef0 T emit_line_note_force +0000000120200290 S emit_lineno +0000000120071c20 T emit_move_insn +0000000120071e90 T emit_move_insn_1 +0000000120191520 T emit_move_sequence +000000012009ba10 T emit_no_conflict_block +000000012006e460 T emit_nop +00000001200b5db0 T emit_note +00000001200b5610 T emit_note_after +00000001200b52c0 T emit_note_before +0000000120072360 T emit_push_insn +00000001200821d0 T emit_queue +0000000120150350 t emit_reload_insns +0000000120095df0 T emit_stack_restore +0000000120094d40 T emit_stack_save +00000001200922d0 T emit_store_flag +00000001201989a0 T emit_test +000000012019dc30 T emit_typecode_conversion +00000001200a0dc0 T emit_unop_insn +000000012010a770 T emit_unrolled_add +00000001200b6990 t emov +00000001200bd500 t emovi +00000001201e9ef8 d emtens +00000001200b7b30 t emul +00000001200bdb40 t emulm +000000012016b090 T end_final +00000001201fed28 s end_of_file +00000001201ff958 s end_of_function_label +0000000120209514 b end_of_function_needs +00000001200b6430 T end_sequence +0000000120042160 T end_temporary_allocation +00000001200bd410 t endian +00000001200b69e0 t eneg +00000001200b9ff0 t enormlz +00000001201fed70 s enum_next_value +00000001201fed78 s enum_overflow +00000001201e9e14 D eone +00000001201e9e50 D epi +00000001201ff0a8 s epilogue +00000001201ffb94 s epilogue_marked +00000001202005b0 S eqdf2_libfunc +0000000120200458 S eqhf2_libfunc +00000001202006b0 S eqsf2_libfunc +00000001202005e0 S eqtf2_libfunc +0000000120197ba0 T equality_op +00000001200f16c0 t equiv_constant +00000001201ff778 s equiv_mem +00000001201ff780 s equiv_mem_modified +0000000120205f5c b equot +00000001202003f0 S eqxf2_libfunc +00000001200b6750 T ereal_atof +00000001200bd250 T ereal_cmp +00000001200bd340 T ereal_from_double +00000001200bd2f0 T ereal_from_float +00000001200bc1b0 T ereal_from_int +00000001200bc7c0 T ereal_from_uint +00000001200bd2b0 T ereal_isneg +00000001200bcd90 T ereal_ldexp +00000001200bc080 T ereal_negate +00000001200bd200 T ereal_to_decimal +00000001200b6840 T ereal_to_int +00000001201e9fb8 d ermsg +0000000120030560 T error +00000001200301d0 T error_for_asm +0000000120021a20 T error_init +00000001201ffd48 S error_mark_node +000000012002ffa0 T error_with_decl +000000012002fcf0 T error_with_file_and_line +00000001201fef44 S errorcount +00000001200b9cc0 t eshift +00000001201ff240 s esqinited +00000001201e9e44 D esqrt2 +000000012006c220 t estimate_case_costs +00000001200b6a90 t esub +00000001200bd090 T etardouble +00000001200bcf80 T etarldouble +00000001200bd0f0 T etarsingle +00000001200bce70 T etartdouble +00000001201e9e5c d etens +00000001200bf010 t etoasc +00000001200b92e0 t etoe53 +00000001200bba10 T etrunci +00000001200bbd60 T etruncui +00000001201e9e20 D etwo +00000001200b9750 t euifrac +000000012004bf50 t eval_subst +0000000120197a00 T even_relop +00000001201fec98 g everything.1 +00000001201fec9c g everything.2 +00000001201feca0 g everything.5 +0000000120038c80 T exact_log2_wide +00000001200e9450 t exp_equiv_p +000000012009ad30 T expand_abs +00000001200921b0 T expand_and +0000000120068e40 T expand_anon_union_decl +000000012006e940 T expand_asm +0000000120064330 T expand_asm_operands +0000000120072c90 T expand_assignment +00000001200962f0 T expand_binop +0000000120196d00 T expand_block_move +000000012007bde0 t expand_builtin +000000012007d3f0 t expand_builtin_apply +000000012007d180 t expand_builtin_apply_args +000000012007dad0 t expand_builtin_return +0000000120082930 T expand_builtin_return_addr +0000000120085050 T expand_call +00000001200690e0 t expand_cleanups +000000012007e6e0 T expand_cleanups_to +000000012009b0c0 T expand_complex_abs +000000012011e640 t expand_compound_operation +000000012006e5f0 T expand_computed_goto +000000012006eed0 T expand_continue_loop +0000000120093170 T expand_dec +0000000120068320 T expand_decl +000000012006f3f0 T expand_decl_cleanup +0000000120068b10 T expand_decl_init +000000012008eaa0 T expand_divmod +000000012006ed50 T expand_elseif +0000000120067850 T expand_end_bindings +000000012006acc0 T expand_end_case +0000000120069630 T expand_end_case_dummy +00000001200658d0 T expand_end_cond +0000000120065d70 T expand_end_loop +00000001200654b0 T expand_end_stmt_expr +000000012006ef30 T expand_exit_loop +000000012006ef90 T expand_exit_loop_if_false +000000012006f160 T expand_exit_something +0000000120075360 T expand_expr +0000000120064f60 T expand_expr_stmt +000000012011e960 t expand_field_assignment +000000012009ddb0 T expand_fix +0000000120063eb0 t expand_fixup +000000012006e920 T expand_fixups +000000012009cf70 T expand_float +00000001200607d0 T expand_function_end +000000012005ff70 T expand_function_start +00000001200639c0 T expand_goto +0000000120063ce0 t expand_goto_internal +00000001200930e0 T expand_inc +000000012007dce0 t expand_increment +00000001200dbc40 T expand_inline_function +000000012006e6a0 T expand_label +000000012006ee30 T expand_loop_continue_here +0000000120063660 T expand_main_function +000000012008da30 T expand_mult +00000001200933d0 T expand_mult_add +000000012008e3a0 T expand_mult_highpart +0000000120093240 T expand_mult_highpart_adjust +000000012006f1d0 T expand_null_return +00000001201374d0 t expand_preferences +0000000120066330 T expand_return +000000012008ce50 T expand_shift +0000000120067600 T expand_start_bindings +0000000120069210 T expand_start_case +0000000120069500 T expand_start_case_dummy +0000000120065700 T expand_start_cond +000000012006ec10 T expand_start_else +000000012006eb00 T expand_start_elseif +0000000120065b90 T expand_start_loop +000000012006edd0 T expand_start_loop_continue_elsewhere +000000012006ea10 T expand_start_stmt_expr +000000012002f4a0 t expand_stmt_with_iterators_1 +00000001200998a0 T expand_twoval_binop +0000000120099f20 T expand_unop +00000001201fed54 S explicit_flag_signed_bitfields +0000000120095510 T expr_size +00000001202002a8 S expr_stmts_for_value +00000001202000b8 S expression_obstack +00000001202003f8 S extenddftf2_libfunc +0000000120200320 S extenddfxf2_libfunc +000000012012bd50 T extended_count +0000000120200658 S extendsfdf2_libfunc +0000000120200418 S extendsftf2_libfunc +0000000120200488 S extendsfxf2_libfunc +000000012020fce0 B extendtab +00000001201fefc4 S extra_warnings +000000012008b320 T extract_bit_field +000000012008c510 t extract_fixed_bit_field +000000012012c9c0 t extract_left_shift +000000012008cb50 t extract_split_bit_field +0000000120205f50 B ezero +00000001201e7a08 D f_options +00000001201ea030 D factors +00000001201ffba8 s failure_errno.1 +00000001201ff2b8 s fake_containing_scope +0000000120038b70 T fancy_abort +0000000120030830 T fatal +000000012002f9d0 T fatal_insn +0000000120038790 T fatal_insn_not_found +0000000120038740 T fatal_io_error +0000000120200688 S ffs_optab +00000001200d9980 t field_byte_offset +0000000120018f00 t field_decl_cmp +00000001201ff270 s filename_table +000000012015b4b0 t fill_eager_delay_slots +0000000120159ed0 t fill_simple_delay_slots +000000012015e3a0 t fill_slots_from_thread +000000012016ca70 T final +000000012010bd30 T final_biv_value +000000012016f890 T final_end_function +000000012010c1d0 T final_giv_value +000000012016cdb0 T final_scan_insn +00000001202009c0 S final_sequence +000000012016f720 T final_start_function +00000001201ffed8 S final_time +00000001201ff264 s finalizing +00000001201003a0 t find_and_verify_loops +000000012010df00 t find_basic_blocks +00000001200f5950 t find_best_addr +00000001200f67a0 t find_comparison_args +0000000120173f60 t find_constant_term_loc +00000001200e3280 t find_cross_jump +000000012013c220 t find_dummy_reload +000000012015cc40 t find_end_label +0000000120143fa0 T find_equiv_reg +0000000120134400 t find_free_reg +0000000120061c20 T find_function_data +0000000120144fc0 t find_inc_amount +00000001200b03c0 T find_last_value +000000012006f5c0 T find_loop_tree_blocks +0000000120103610 t find_mem_givs +0000000120093b30 T find_next_ref +0000000120137ba0 t find_reg +00000001200ae880 T find_reg_fusage +00000001200b09c0 T find_reg_note +00000001200ae9e0 T find_regno_fusage +00000001200b0a20 T find_regno_note +000000012013d610 T find_reloads +0000000120141490 t find_reloads_address +0000000120142720 t find_reloads_address_1 +0000000120143360 t find_reloads_address_part +0000000120140ed0 t find_reloads_toplev +0000000120145e60 T find_replacement +0000000120173060 T find_single_use +0000000120170dc0 t find_single_use_1 +0000000120107b10 t find_single_use_in_loop +0000000120117900 t find_split_point +000000012010aff0 t find_splittable_givs +000000012010a800 t find_splittable_regs +0000000120164a10 t find_symbolic_term +0000000120111f40 t find_use_as_address +0000000120010df0 T finish_decl +0000000120014560 T finish_enum +0000000120006fb0 T finish_file +0000000120015fe0 T finish_function +0000000120016430 T finish_incomplete_decl +00000001200257e0 T finish_init +0000000120013a60 T finish_struct +0000000120200010 S finput +00000001202006d8 S first_global_object_name +00000001201ff1e8 s first_insn +00000001201ff210 s first_label_num +00000001201ff190 s first_pool +000000012005ed80 T fix_lexical_addr +0000000120130180 T fix_register +00000001202003b0 S fixdfdi_libfunc +0000000120200370 S fixdfsi_libfunc +00000001202002f8 S fixdfti_libfunc +0000000120200920 S fixed_reg_set +0000000120213bec B fixed_regs +0000000120200468 S fixsfdi_libfunc +00000001202005f0 S fixsfsi_libfunc +0000000120200368 S fixsfti_libfunc +000000012020c850 B fixtab +0000000120200400 S fixtfdi_libfunc +00000001202003a0 S fixtfsi_libfunc +00000001202004c0 S fixtfti_libfunc +0000000120211728 B fixtrunctab +00000001202005c8 S fixunsdfdi_libfunc +00000001202004e8 S fixunsdfsi_libfunc +00000001202005a0 S fixunsdfti_libfunc +0000000120200378 S fixunssfdi_libfunc +0000000120200448 S fixunssfsi_libfunc +0000000120200328 S fixunssfti_libfunc +00000001202003c8 S fixunstfdi_libfunc +00000001202006b8 S fixunstfsi_libfunc +00000001202003b8 S fixunstfti_libfunc +0000000120200310 S fixunsxfdi_libfunc +00000001202004f8 S fixunsxfsi_libfunc +0000000120200650 S fixunsxfti_libfunc +000000012006f820 t fixup_gotos +000000012005bd20 t fixup_memory_subreg +00000001200493d0 T fixup_signed_type +000000012005c060 t fixup_stack_1 +00000001200494e0 T fixup_unsigned_type +000000012005aaa0 t fixup_var_refs +000000012005afa0 t fixup_var_refs_1 +000000012005ac10 t fixup_var_refs_insns +0000000120200318 S fixxfdi_libfunc +0000000120200630 S fixxfsi_libfunc +0000000120200490 S fixxfti_libfunc +00000001201fed50 S flag_allow_single_precision +00000001201fef74 S flag_caller_saves +00000001201ffc40 S flag_cond_mismatch +00000001201fff28 S flag_cse_follow_jumps +00000001201fff98 S flag_cse_skip_blocks +00000001201fef84 S flag_defer_pop +0000000120200024 S flag_delayed_branch +00000001201fff88 S flag_expensive_optimizations +00000001201fef9c S flag_fast_math +00000001201fef88 S flag_float_store +00000001201fef80 S flag_force_addr +00000001201fef7c S flag_force_mem +00000001201fefa4 S flag_gen_aux_info +00000001201fec24 G flag_gnu_linker +00000001201fefb4 S flag_inhibit_size_directive +00000001201ffef8 S flag_inline_functions +00000001201ffecc S flag_keep_inline_functions +00000001201fec78 g flag_minimal_debug +00000001201ffe50 S flag_no_asm +00000001201ffc98 S flag_no_builtin +0000000120200008 S flag_no_common +00000001201fef90 S flag_no_function_cse +00000001201fed58 S flag_no_ident +00000001201fff68 S flag_no_inline +00000001201ffc94 S flag_no_nonansi_builtin +00000001201fef98 S flag_no_peephole +00000001201fef94 S flag_omit_frame_pointer +00000001201fefbc S flag_pack_struct +00000001201fef78 S flag_pcc_struct_return +00000001201fefa8 S flag_pedantic_errors +00000001201fffdc S flag_pic +00000001201ffec8 S flag_pretend_float +00000001201fef30 S flag_print_asm_name +00000001201fefdc s flag_rerun_cse_after_loop +00000001201fefac S flag_schedule_insns +00000001201fefb0 S flag_schedule_insns_after_reload +0000000120200030 S flag_shared_data +00000001201ffe20 S flag_short_double +00000001201ffee8 S flag_short_enums +00000001201fffb8 S flag_short_temps +00000001201fec0c G flag_signed_bitfields +00000001201fff48 S flag_signed_char +00000001201fef8c S flag_strength_reduce +00000001201fefa0 S flag_syntax_only +00000001201fff08 S flag_thread_jumps +00000001201ffdf8 S flag_traditional +00000001201fff94 S flag_unroll_all_loops +00000001201fec1c G flag_unroll_loops +00000001201fefb8 S flag_verbose_asm +00000001201fff60 S flag_volatile +0000000120200068 S flag_volatile_global +00000001201fec20 G flag_writable_strings +00000001202033e8 b float_error +00000001201ffd88 S float_ftype_float +00000001201fff0c S float_handled +000000012020ba18 B float_handler +00000001200394c0 t float_signal +00000001201ffdd0 S float_type_node +0000000120200648 S floatdidf_libfunc +00000001202004b8 S floatdisf_libfunc +0000000120200638 S floatditf_libfunc +0000000120200668 S floatdixf_libfunc +0000000120200380 S floatsidf_libfunc +0000000120200528 S floatsisf_libfunc +00000001202004a0 S floatsitf_libfunc +00000001202003e0 S floatsixf_libfunc +000000012020e298 B floattab +00000001202003a8 S floattidf_libfunc +0000000120200530 S floattisf_libfunc +00000001202005f8 S floattitf_libfunc +0000000120200338 S floattixf_libfunc +0000000120200438 S flodiv_optab +0000000120038ce0 T floor_log2_wide +000000012010db80 T flow_analysis +000000012010eea0 t flow_delete_insn +00000001201fef10 S flow_dump +0000000120200048 S flow_dump_file +0000000120200040 S flow_time +0000000120164f30 t flush_pending_lists +000000012004c5f0 T fold +0000000120056820 t fold_convert +00000001200ee250 t fold_rtx +0000000120057700 t fold_truthop +00000001200e3cc0 T follow_jumps +000000012020099c S forbidden_regs +00000001200a69e0 T force_const_mem +0000000120049f20 T force_fit_type +00000001200fe2a0 t force_movables +00000001200b5f10 T force_next_line_note +0000000120095a00 T force_not_mem +0000000120074c00 T force_operand +0000000120094bf0 T force_reg +0000000120120540 t force_to_mode +00000001202007f8 S forced_labels +000000012014e490 t forget_old_reloads_1 +000000012000b7d0 T forget_protocol_qualifiers +0000000120145b80 T form_sum +000000012018f1c0 t fpadd100_unit_blockage +000000012018b860 T fpadd100_unit_blockage_range +000000012018b5e0 T fpadd100_unit_ready_cost +000000012018ef60 t fpadd110_unit_blockage +000000012018b460 T fpadd110_unit_blockage_range +000000012018ec40 T fpadd110_unit_ready_cost +000000012018fa70 t fpmul100_unit_blockage +000000012018bb20 T fpmul100_unit_blockage_range +000000012018ba30 T fpmul100_unit_ready_cost +000000012018ed00 T fpmul110_unit_ready_cost +0000000120001a80 t frame_dummy +00000001201ffb88 s frame_laid_out +00000001202001d8 S frame_offset +00000001202009ac S frame_pointer_needed +00000001202007c0 S frame_pointer_rtx +00000001201ffb8c s frame_size +00000001201fedd8 s free_binding_level +00000001200e7f30 t free_element +00000001201ff420 s free_element_chain +00000001201688c0 t free_pending_lists +0000000120062020 T free_temp_slots +0000000120062090 T free_temps_for_rtl_expr +00000001201ff27c s ft_entries +00000001201ff278 s ft_entries_allocated +0000000120200498 S ftrunc_optab +0000000120200284 S function_call_count +00000001200da320 T function_cannot_inline_p +00000001201ff160 s function_defined +00000001201feed0 s function_format_list +00000001202000f0 S function_maybepermanent_obstack +00000001202000c8 S function_obstack +00000001200a8830 T function_section +00000001200199a0 t function_types_compatible_p +00000001201eb100 D function_units +000000012018ced0 T function_units_used +00000001200ce960 t fundamental_type_code +00000001201fff9c S g_switch_set +00000001201ffeb0 S g_switch_value +000000012003bd90 T gcc_obstack_init +0000000120200360 S gedf2_libfunc +00000001202003d0 S gehf2_libfunc +000000012018a050 T gen_absdf2 +000000012018a0c0 T gen_abssf2 +00000001200a1330 T gen_add2_insn +0000000120188dc0 T gen_adddf3 +0000000120188f50 T gen_adddi3 +0000000120188ee0 T gen_addsf3 +0000000120188d50 T gen_addsi3 +00000001201898e0 T gen_anddi3 +00000001201815c0 T gen_andsi3 +0000000120181aa0 T gen_ashlsi3 +0000000120181f00 T gen_ashrsi3 +0000000120028650 T gen_aux_info_record +0000000120185ee0 T gen_bcnd +0000000120186100 T gen_beq +0000000120186a80 T gen_bge +0000000120186bd0 T gen_bgeu +00000001201863a0 T gen_bgt +00000001201864f0 T gen_bgtu +0000000120126bf0 t gen_binary +0000000120186df0 T gen_ble +0000000120186f40 T gen_bleu +000000012018a630 T gen_blockage +0000000120186710 T gen_blt +0000000120186860 T gen_bltu +0000000120186250 T gen_bne +0000000120185ff0 T gen_bxx +000000012018a130 T gen_call +0000000120187a30 T gen_call_block_move +0000000120187dc0 T gen_call_movstrsi_loop +000000012018a2e0 T gen_call_value +0000000120182830 T gen_casesi +0000000120182fc0 T gen_casesi_enter +0000000120182de0 T gen_casesi_jump +0000000120185360 T gen_cmpdf +0000000120185260 T gen_cmpsf +0000000120185120 T gen_cmpsi +0000000120027d40 t gen_decl +000000012018a6d0 T gen_decrement_and_branch_until_zero +0000000120181340 T gen_divdf3 +0000000120189870 T gen_divsf3 +000000012017f050 T gen_divsi3 +0000000120183160 T gen_dummy +000000012018a590 T gen_epilogue +00000001200a15e0 T gen_extend_insn +0000000120188720 T gen_extendhisi2 +0000000120188850 T gen_extendqihi2 +0000000120188980 T gen_extendqisi2 +0000000120188ab0 T gen_extendsfdf2 +00000001201885a0 T gen_extendsidi2 +0000000120189e90 T gen_extv +0000000120189f00 T gen_extzv +0000000120189d60 T gen_ffssi2 +0000000120188c70 T gen_fix_truncdfsi2 +0000000120188ce0 T gen_fix_truncsfsi2 +0000000120188b90 T gen_floatsidf2 +0000000120188c00 T gen_floatsisf2 +0000000120028c20 t gen_formal_list_for_func_def +00000001200287b0 t gen_formal_list_for_type +00000001200b1bf0 T gen_highpart +00000001200b3e60 T gen_imagpart +000000012018a690 T gen_indirect_jump +00000001200b43f0 T gen_inline_header_rtx +0000000120189950 T gen_iordi3 +0000000120181780 T gen_iorsi3 +0000000120183100 T gen_jump +00000001200b4360 T gen_label_rtx +0000000120187160 T gen_locate1 +0000000120187220 T gen_locate2 +00000001200b4000 T gen_lowpart +00000001200b14c0 T gen_lowpart_common +00000001201265a0 t gen_lowpart_for_combine +00000001200f1980 T gen_lowpart_if_possible +0000000120182360 T gen_lshrsi3 +00000001201833f0 T gen_m88k_rcs_id +00000001201877a0 T gen_movdf +00000001201876d0 T gen_movdi +000000012009cbd0 T gen_move_insn +0000000120187530 T gen_movhi +0000000120187600 T gen_movqi +0000000120187870 T gen_movsf +0000000120187370 T gen_movsi +0000000120187940 T gen_movstrsi +00000001201893a0 T gen_muldf3 +00000001201894c0 T gen_mulsf3 +0000000120189330 T gen_mulsi3 +0000000120189f70 T gen_negdf2 +0000000120189fe0 T gen_negsf2 +00000001201827c0 T gen_negsi2 +000000012018a4c0 T gen_nop +0000000120189aa0 T gen_one_cmpldi2 +0000000120189a30 T gen_one_cmplsi2 +000000012018a520 T gen_prologue +00000001200828f0 T gen_push_operand +00000001200b3e10 T gen_realpart +00000001200b1290 T gen_reg_rtx +0000000120151de0 T gen_reload +0000000120187440 T gen_reload_insi +000000012018a4e0 T gen_return +0000000120189b70 T gen_rotlsi3 +0000000120189cf0 T gen_rotrsi3 +00000001200b1100 T gen_rtvec +00000001200b1210 T gen_rtvec_v +00000001200b0e00 T gen_rtx +00000001201269a0 t gen_rtx_combine +00000001201854a0 T gen_seq +00000001200b64a0 T gen_sequence +0000000120185920 T gen_sge +00000001201859e0 T gen_sgeu +0000000120185620 T gen_sgt +00000001201856e0 T gen_sgtu +0000000120185aa0 T gen_sle +0000000120185b60 T gen_sleu +00000001201857a0 T gen_slt +0000000120185860 T gen_sltu +0000000120185560 T gen_sne +0000000120183430 T gen_split_1 +000000012017eed0 T gen_split_125 +000000012017e110 T gen_split_13 +000000012017e390 T gen_split_14 +000000012017e5a0 T gen_split_15 +0000000120184140 T gen_split_16 +00000001201842e0 T gen_split_17 +0000000120184450 T gen_split_18 +000000012017e7f0 T gen_split_19 +0000000120183610 T gen_split_2 +000000012017ea70 T gen_split_20 +000000012017ec80 T gen_split_21 +00000001201845e0 T gen_split_22 +0000000120184780 T gen_split_23 +00000001201848f0 T gen_split_24 +00000001201837f0 T gen_split_3 +0000000120184a80 T gen_split_31 +0000000120184bb0 T gen_split_33 +0000000120184d00 T gen_split_35 +0000000120184e30 T gen_split_37 +00000001201839d0 T gen_split_4 +0000000120183bb0 T gen_split_5 +0000000120183d90 T gen_split_6 +0000000120183f70 T gen_split_7 +0000000120185c20 T gen_split_75 +0000000120185d70 T gen_split_80 +00000001200a1470 T gen_sub2_insn +00000001201890b0 T gen_subdf3 +0000000120189240 T gen_subdi3 +00000001201891d0 T gen_subsf3 +0000000120189040 T gen_subsi3 +0000000120189b10 T gen_tbnd +0000000120189570 T gen_tcnd_divide_by_zero +0000000120184f80 T gen_test +0000000120189530 T gen_trap_divide_by_zero +0000000120188b20 T gen_truncdfsf2 +0000000120026a00 t gen_type +0000000120180e90 T gen_udivsi3 +0000000120126f10 t gen_unary +00000001201899c0 T gen_xordi3 +0000000120181920 T gen_xorsi3 +00000001201881f0 T gen_zero_extendhisi2 +0000000120188320 T gen_zero_extendqihi2 +0000000120188450 T gen_zero_extendqisi2 +00000001201049d0 t general_induction_var +0000000120171140 T general_operand +0000000120200428 S gesf2_libfunc +000000012018ee20 T get_attr_cpu +000000012018d8b0 T get_attr_fpu +000000012016be50 T get_attr_length +000000012018da20 T get_attr_type +0000000120048ce0 T get_best_mode +0000000120157380 t get_branch_condition +0000000120107100 T get_condition +0000000120107760 T get_condition_for_loop +000000012002c580 T get_directive_line +0000000120041c40 T get_file_function_name +0000000120062d80 T get_first_block_beg +00000001200b3df0 T get_first_label_num +0000000120062d30 T get_first_nonparm_insn +0000000120061cb0 T get_frame_size +000000012003d8a0 T get_identifier +00000001200746b0 T get_inner_reference +00000001200745e0 t get_inner_unaligned_p +00000001200b4830 T get_insns +00000001200afcb0 T get_integer_term +0000000120156dd0 t get_jump_flags +00000001200e39a0 T get_label_after +00000001200e3910 T get_label_before +00000001200b4850 T get_last_insn +00000001200b48b0 T get_last_insn_anywhere +00000001201299d0 t get_last_value +00000001201297d0 t get_last_value_validate +00000001200b4900 T get_max_uid +0000000120041960 T get_narrower +0000000120013760 T get_parm_info +0000000120048e70 T get_pending_sizes +00000001200842e0 t get_pointer_alignment +00000001200a9760 T get_pool_constant +00000001200a9830 T get_pool_mode +00000001200a9900 T get_pool_offset +00000001200a99d0 T get_pool_size +00000001200afd30 T get_related_value +00000001200384e0 T get_run_time +0000000120041e00 T get_set_constructor_bits +0000000120041fc0 T get_set_constructor_bytes +0000000120021790 t get_spelling +00000001200416b0 T get_unwidened +0000000120016e20 T getdecls +0000000120200580 S getf2_libfunc +0000000120198ed0 T getpwd +0000000120016e40 T gettags +0000000120200678 S gexf2_libfunc +0000000120135fa0 T global_alloc +0000000120200090 S global_alloc_time +00000001201fede0 s global_binding_level +00000001200164d0 T global_bindings_p +0000000120136f90 t global_conflicts +00000001202007e8 S global_const_equiv_map +00000001202007f0 S global_const_equiv_map_size +00000001201fef20 S global_reg_dump +0000000120200078 S global_reg_dump_file +0000000120213d0c B global_regs +0000000120130270 T globalize_reg +00000001201ff0e0 s goto_fixup_chain +0000000120011750 t grokdeclarator +0000000120017710 T grokfield +0000000120013550 t grokparms +0000000120016ee0 T groktypename +0000000120016f20 T groktypename_in_parm_context +000000012006c550 t group_case_nodes +0000000120200340 S gtdf2_libfunc +0000000120200670 S gthf2_libfunc +0000000120200500 S gtsf2_libfunc +0000000120200460 S gttf2_libfunc +0000000120200598 S gtxf2_libfunc +000000012000c110 T handle_pragma_token +00000001200a99f0 T handle_pragma_weak +0000000120008c80 T handle_sysv_pragma +00000001202007e0 S hard_frame_pointer_rtx +0000000120095f70 T hard_function_value +0000000120096090 T hard_libcall_value +00000001201ff7d0 s hard_reg_conflicts +00000001201ff7e0 s hard_reg_copy_preferences +00000001201ff7e8 s hard_reg_full_preferences +00000001201ff7d8 s hard_reg_preferences +000000012013c7e0 t hard_reg_set_here_p +0000000120152d20 t hard_reg_use_compare +00000001201ff3d8 s hard_regs_in_table +00000001201ff7c4 s hard_regs_live +00000001201ff938 s hard_regs_live +00000001201ff85c s hard_regs_live_known +00000001201ff948 s hard_regs_need_restore +00000001201ff940 s hard_regs_saved +00000001201ff418 s hash_arg_in_memory +00000001201ff41c s hash_arg_in_struct +0000000120201258 b hash_table +0000000120209db8 b hashtab +00000001200a1440 T have_add2_insn +00000001200a1580 T have_sub2_insn +00000001201ff244 s have_used_extensions +00000001201ffae8 s high_block_linenum +00000001201ffaec s high_function_linenum +00000001201ff120 s highest_outgoing_arg_in_use +00000001201ff6a8 s highest_regno_in_uid_map +00000001201ffff0 S id_clash_len +00000001201feff8 S id_string_size +000000012005f2a0 T identify_blocks +00000001201fecf8 s if_stmt_file +00000001201fed00 s if_stmt_line +00000001201219a0 t if_then_else_cond +00000001200fe1d0 t ignore_some_movables +00000001200a4ad0 T immed_double_const +00000001200a9420 T immed_real_const +00000001200a4d30 T immed_real_const_1 +00000001201732d0 T immediate_operand +0000000120200148 S immediate_size_expand +00000001200169f0 T implicitly_declare +00000001201ff08c s in_arg_offset +00000001201ff168 s in_named_name +00000001201ff308 s in_nonparm_insns +00000001200165c0 T in_parm_level_p +00000001201ff148 s in_section +00000001200b6480 T in_sequence_p +00000001201fef68 S in_system_header +00000001200a86e0 T in_text_section +0000000120152660 t inc_for_reload +00000001201fef58 S incomplete_decl_finalize_hook +0000000120018f40 T incomplete_type_error +00000001201ff1b4 s indent.0 +0000000120047830 T indent_to +0000000120044df0 T index_type_equal +0000000120173810 T indirect_operand +0000000120200999 S indirect_symref_ok +00000001200af270 T inequality_comparisons_p +00000001202002ec S inhibit_defer_pop +00000001201fefc0 S inhibit_warnings +00000001201ff348 s init.0 +00000001201ff34c s init.3 +00000001201ff350 s init.4 +00000001201641d0 T init_alias_analysis +00000001201740b0 T init_all_optabs +00000001201549c0 T init_caller_save +00000001200a9560 T init_const_rtx_hash_table +000000012000e5d0 T init_decl_processing +00000001200b35a0 T init_emit +00000001200b3800 T init_emit_once +0000000120089c70 T init_expmed +0000000120082040 T init_expr +000000012006ff10 T init_expr_once +000000012016f630 T init_final +000000012002cb10 T init_function_format_info +000000012005f5e0 T init_function_start +000000012016f700 T init_insn_lengths +000000012002e8e0 T init_iterators +0000000120007110 T init_lex +00000001200a1640 t init_libfuncs +0000000120107800 T init_loop +000000012018a8b0 T init_mov_optab +0000000120084200 t init_noncopied_parts +000000012003b990 T init_obstacks +000000012009ecb0 T init_optabs +0000000120082a70 T init_pending_stack_adjust +0000000120172e30 T init_recog +0000000120172e10 T init_recog_no_volatile +0000000120114280 t init_reg_last_arrays +0000000120109a30 t init_reg_map +0000000120130b10 t init_reg_modes +000000012012d1e0 T init_reg_sets +00000001201307a0 t init_reg_sets_1 +000000012012fec0 T init_regs +000000012010ff40 t init_regset_vector +0000000120147440 T init_reload +00000001200ac2b0 T init_rtl +0000000120156100 T init_save_areas +000000012006e240 T init_stmt +000000012006e270 T init_stmt_for_function +00000001200425f0 T init_tree_codes +00000001201ea0f8 d initial_call_used_regs +00000001201ea0b8 d initial_fixed_regs +000000012010d3a0 t initial_reg_note_copy +00000001201ff028 s initial_trampoline.1 +00000001201ffea0 S initialization_message +00000001200dfa70 t initialize_for_inline +00000001201ff26c s initialized.2 +00000001200213c0 T initializer_constant_valid_p +00000001201ffe90 S initializer_stack +0000000120200198 S inline_function_decl +0000000120200108 S inline_obstacks +00000001201fff20 S input_file_stack +000000012020000c S input_file_stack_tick +00000001201fffc0 S input_filename +00000001200e7f50 t insert +00000001200167b0 T insert_block +00000001200e7ab0 t insert_regs +0000000120155d20 t insert_save_restore +00000001202009b8 S insn_addresses +00000001201ff9f0 s insn_blockage +0000000120164cf0 t insn_cost +00000001201ff9e0 s insn_costs +00000001201ffac8 s insn_counter +00000001202009b4 S insn_current_address +000000012018ea90 T insn_current_length +00000001201109b0 t insn_dead_p +000000012018a8c0 T insn_default_length +000000012017c590 T insn_extract +00000001201bf238 R insn_gen_function +00000001201ffb28 s insn_lengths +00000001201ff9d0 s insn_luid +00000001201ff2d8 s insn_map +00000001201cec10 R insn_n_alternatives +00000001201bff7c R insn_n_dups +00000001201bfb10 R insn_n_operands +00000001201ea800 D insn_name +00000001201fecc8 G insn_name_ptr +00000001201ffb08 s insn_noperands +00000001201c03e8 R insn_operand_constraint +00000001201c5c58 R insn_operand_mode +00000001201c93a0 R insn_operand_predicate +00000001201c8890 R insn_operand_strict_low +00000001201be960 R insn_outfun +00000001201ff9d8 s insn_priority +0000000120209570 b insn_queue +00000001201ff9f8 s insn_ref_count +00000001201be088 R insn_template +00000001201ffa38 s insn_tick +00000001201ff9e8 s insn_units +000000012018eb20 T insn_variable_length_p +0000000120063780 t instantiate_decls_1 +00000001200621a0 T instantiate_virtual_regs +000000012005c860 t instantiate_virtual_regs_1 +0000000120197760 T int32_operand +0000000120197730 T int5_operand +00000001201ffcf8 S intDI_type_node +00000001201ffd08 S intHI_type_node +00000001201ffc78 S intQI_type_node +00000001201ffcd8 S intSI_type_node +00000001201ffdb0 S int_array_type_node +0000000120045270 T int_fits_type_p +00000001201ffe08 S int_ftype_cptr_cptr_sizet +00000001201ffd30 S int_ftype_int +00000001201ffca8 S int_ftype_ptr_ptr_int +00000001201ffde0 S int_ftype_string_string +00000001201ea238 d int_reg_class_contents +0000000120043a30 T int_size_in_bytes +0000000120042cf0 T integer_all_onesp +0000000120196960 T integer_ok_for_set +00000001201ffd58 S integer_one_node +0000000120042b90 T integer_onep +0000000120042ef0 T integer_pow2p +00000001201ffe80 S integer_type_node +00000001201ffd68 S integer_zero_node +0000000120042ac0 T integer_zerop +00000001200dd810 t integrate_decl_tree +00000001200dd710 t integrate_parm_decls +00000001201ffefc S integration_time +00000001200387c0 T interim_eh +0000000120200088 S interim_eh_hook +0000000120025d50 t internal_build_compound_expr +00000001200e87e0 t invalidate +00000001200f5710 t invalidate_for_call +00000001200f2dd0 t invalidate_from_clobbers +00000001200fb1e0 t invalidate_skipped_set +0000000120100fe0 T invariant_p +00000001200e4a60 T invert_exp +00000001200e6f60 T invert_jump +000000012004c250 T invert_truthvalue +0000000120200538 S ior_optab +0000000120044300 T is_attribute_p +0000000120006eb0 T is_class_name +000000012000b660 T is_reserved_word +00000001201ffea8 S iter_stack +000000012010d480 t iteration_info +000000012002ef90 T iterator_expand +000000012002ee60 T iterator_for_loop_end +000000012002ed40 T iterator_for_loop_start +00000001201feee8 s ixp_firstobj +0000000120201150 b ixp_obstack +00000001201fef28 S jump2_opt_dump +00000001201fffc8 S jump2_opt_dump_file +00000001200e3a30 t jump_back_p +00000001201ff318 s jump_chain +00000001201fef00 S jump_opt_dump +00000001201fffb0 S jump_opt_dump_file +00000001200e0140 T jump_optimize +0000000120200070 S jump_time +000000012007e7c0 T jumpif +000000012007e790 T jumpifnot +00000001201ffb38 s junk +00000001201fedec s keep_next_if_subblocks +00000001200164f0 T keep_next_level +00000001201fede8 s keep_next_level_flag +0000000120016510 T kept_level_p +00000001201222b0 t known_cond +00000001202034f8 b label.4 +00000001201ff0f8 s label_counter.3 +00000001201fedf0 s label_level_chain +00000001201ff2d0 s label_map +00000001201fec50 g label_num +000000012006e510 T label_rtx +00000001201ff628 s label_tick +00000001201ff14c s labelno.1 +00000001201ff150 s labelno.2 +0000000120200a30 S labelrefs +0000000120200a38 S labels +0000000120100f60 t labels_in_range_p +0000000120006de0 T lang_decode_option +00000001201fffa0 S lang_expand_expr +0000000120006e60 T lang_finish +0000000120006e70 T lang_identify +0000000120006e10 T lang_init +00000001201e7db0 D lang_options +00000001201fec00 G language_string +00000001201fff5c S larger_than_size +00000001201ffb78 s last_addr.2 +00000001202006d0 S last_assemble_variable_decl +00000001201ff0c8 s last_block_end_note +00000001201ff5d4 s last_call_cuid +00000001201ff558 s last_call_suid +000000012006f4d0 T last_cleanup_this_contour +00000001201fefd0 s last_error_function +00000001201fefec s last_error_tick +00000001201ff0b8 s last_expr_type +00000001201ff0c0 s last_expr_value +00000001201ff208 s last_filename +00000001201ff288 s last_filename +00000001201ffaf0 s last_filename +00000001201ffa98 s last_function_call +00000001201fed88 s last_function_parm_tags +00000001201fed80 s last_function_parms +00000001201ffac0 s last_ignored_compare +00000001201ff1f0 s last_insn +00000001201ff430 s last_jump_equiv_class +00000001201ff214 s last_label_num +00000001201ff268 s last_line_entry_num.0 +00000001201ff200 s last_linenum +00000001201ffae4 s last_linenum +00000001201ff540 s last_mem_set +00000001201ff048 s last_parm_insn +00000001201ffa90 s last_pending_memory_flush +00000001201ff198 s last_pool +00000001201ffaa8 s last_scheduled_insn +00000001201ff8ac s last_spill_reg +0000000120106ed0 t last_use_this_basic_block +00000001201ffbf0 S lastiddecl +00000001200144f0 t layout_array_type +00000001200478c0 T layout_decl +00000001200495d0 t layout_record +0000000120047db0 T layout_type +0000000120049bc0 t layout_union +00000001201ffe00 S ldouble_ftype_ldouble +00000001201ea470 d leaf.0 +00000001202009c8 S leaf_function +000000012016fa00 T leaf_function_p +0000000120200480 S ledf2_libfunc +0000000120191870 T legitimize_address +0000000120197110 T legitimize_operand +0000000120200330 S lehf2_libfunc +00000001202005c0 S lesf2_libfunc +0000000120200560 S letf2_libfunc +00000001202003d8 S lexf2_libfunc +00000001200fe070 t libcall_benefit +0000000120110c60 t libcall_dead_p +00000001200fdec0 t libcall_other_reg +000000012010eec0 t life_analysis +00000001201ffa00 s line_note +00000001201ffb20 s line_note_exists +00000001201ffa08 s line_note_head +00000001201feff0 s line_position +0000000120200094 S lineno +00000001200435d0 T list_length +00000001200436d0 T listify +0000000120130d90 T local_alloc +00000001201fff8c S local_alloc_time +00000001201fef1c S local_reg_dump +00000001201ffeb8 S local_reg_dump_file +0000000120206f90 b local_reg_live_length +0000000120206e90 b local_reg_n_refs +00000001202001e0 S local_vars_size +000000012005e850 T locate_and_pad_parm +00000001200d9aa0 t location_attribute +00000001200d78e0 t location_or_const_value_attribute +00000001201ffca0 S long_double_type_node +00000001201ffc88 S long_ftype_long +00000001201ffd50 S long_integer_type_node +00000001201ffe40 S long_long_integer_type_node +00000001201ffd18 S long_long_unsigned_type_node +00000001201ffe88 S long_unsigned_type_node +00000001200444f0 T lookup_attribute +000000012001a760 t lookup_field +00000001200cdce0 t lookup_filename +0000000120006ea0 T lookup_interface +0000000120016b90 T lookup_label +000000012000e4c0 T lookup_name +000000012000e500 T lookup_name_current_level +000000012000e560 T lookup_name_current_level_global +0000000120063370 T lookup_static_chain +00000001201ff470 s loop_continue +00000001201ff6a4 s loop_cost +00000001201ff538 s loop_depth +00000001201ff6a0 s loop_depth +00000001201ff770 s loop_depth +00000001201fef08 S loop_dump +0000000120200050 S loop_dump_file +0000000120200820 S loop_dump_stream +00000001201ff4f0 s loop_final_value +00000001201ff468 s loop_has_call +00000001201ff46c s loop_has_volatile +00000001201ff4e8 s loop_increment +00000001201ff4e0 s loop_initial_value +00000001201ff460 s loop_invalid +00000001201ff4d8 s loop_iteration_var +000000012010c720 T loop_iterations +0000000120200848 S loop_iv_list +0000000120200808 S loop_n_iterations +0000000120200840 S loop_number_exit_count +0000000120200810 S loop_number_exit_labels +00000001201ff458 s loop_number_loop_ends +00000001201ff450 s loop_number_loop_starts +00000001200fc370 T loop_optimize +0000000120200818 S loop_outer_loop +0000000120101da0 t loop_reg_used_before_p +00000001202002c0 S loop_stack +0000000120206608 b loop_store_mems +00000001201ff498 s loop_store_mems_idx +00000001201ffed0 S loop_time +00000001201ff4a8 s loops_enclosed +0000000120055f40 T lrotate_double +0000000120055db0 T lshift_double +000000012008cab0 t lshift_value +00000001202006c0 S lshr_optab +00000001202005a8 S ltdf2_libfunc +0000000120200548 S lthf2_libfunc +0000000120200518 S ltsf2_libfunc +0000000120200470 S lttf2_libfunc +0000000120200430 S ltxf2_libfunc +000000012001f0a0 T lvalue_or_else +000000012001eff0 T lvalue_p +00000001200c0300 t m16m +0000000120197de0 T m88k_begin_epilogue +0000000120197cd0 T m88k_begin_prologue +0000000120195430 T m88k_builtin_saveregs +0000000120200a08 S m88k_case_index +0000000120200a00 S m88k_compare_op0 +0000000120200a18 S m88k_compare_op1 +00000001202009e8 S m88k_compare_reg +00000001202009e0 S m88k_cpu +0000000120198220 T m88k_debugger_offset +0000000120197e80 T m88k_end_epilogue +0000000120197cf0 T m88k_end_prologue +0000000120198160 T m88k_expand_epilogue +0000000120194880 T m88k_expand_prologue +00000001201ffb4c S m88k_fp_offset +00000001201987f0 T m88k_function_arg +00000001201ffb48 S m88k_function_number +00000001201ffb40 S m88k_gp_threshold +0000000120194400 T m88k_layout_frame +00000001201fecd0 G m88k_pound_sign +00000001201ffb44 S m88k_prologue_done +0000000120200a10 S m88k_short_data +00000001201ffb50 S m88k_stack_size +00000001202009f0 S m88k_version +00000001202009f8 S m88k_volatile_code +00000001201eb4a8 d m_options +0000000120036b90 T main +0000000120200028 S main_input_filename +0000000120197800 T mak_mask_p +000000012011f8b0 t make_compound_operation +00000001200a1df0 T make_decl_rtl +000000012011ed90 t make_extraction +0000000120122800 t make_field_assignment +00000001200a1880 T make_function_rtl +00000001200b4bf0 T make_insn_raw +00000001200bb910 t make_nan +000000012003d170 T make_node +000000012000b790 T make_pointer_declarator +000000012015c790 t make_return_insns +00000001200b46f0 T make_safe_from +0000000120049170 T make_signed_type +0000000120091e70 T make_tree +000000012003e220 T make_tree_vec +00000001200492c0 T make_unsigned_type +00000001200a89c0 T make_var_volatile +000000012001f3c0 T mark_addressable +0000000120139ec0 T mark_elimination +000000012014b680 T mark_home_live +00000001200e3f10 t mark_jump_label +000000012010ecc0 t mark_label_ref +0000000120134950 t mark_life +0000000120100be0 t mark_loop_jump +00000001200e7250 t mark_modified_reg +0000000120152c40 t mark_not_eliminable +0000000120156280 t mark_referenced_resources +0000000120139030 t mark_reg_clobber +0000000120139220 t mark_reg_conflicts +0000000120139370 t mark_reg_death +00000001201394c0 t mark_reg_live_nc +00000001200b3d50 T mark_reg_pointer +0000000120138df0 t mark_reg_store +0000000120152e70 t mark_reload_reg_in_use +000000012014b750 t mark_scratch_live +000000012006a560 T mark_seen_cases +0000000120110e70 t mark_set_1 +0000000120110d50 t mark_set_regs +0000000120156860 t mark_set_resources +00000001200df8d0 T mark_stores +0000000120158370 t mark_target_live_regs +0000000120061e00 T mark_temp_addr_taken +0000000120111510 t mark_used_regs +000000012012a230 t mark_used_regs_combine +0000000120063640 T mark_varargs +000000012008c9c0 t mask_rtx +00000001201ff788 s max_allocno +00000001201ffb0c s max_block_depth +00000001201ff42c s max_elements_made +00000001201eb3f4 d max_from_align +00000001201ff320 s max_jump_chain +00000001200b3db0 T max_label_num +00000001201ff44c s max_loop_num +00000001201ff448 s max_luid +0000000120200930 S max_parallel +00000001201ff050 s max_parm_reg +00000001201ff2e8 s max_parm_reg +0000000120062d10 T max_parm_reg_num +00000001201ffab0 s max_priority +00000001201ff358 s max_qty +00000001201ff354 s max_reg +0000000120200830 S max_reg_before_loop +00000001200b3d90 T max_reg_num +00000001202008a4 S max_regno +0000000120200880 S max_scratch +0000000120200158 S max_stack_depth +00000001201ff408 s max_uid +00000001201ff978 s max_uid +00000001201ff5b8 s max_uid_cuid +00000001201ff4f8 s max_uid_for_flow +0000000120200868 S max_uid_for_loop +000000012020014c S maximum_field_alignment +00000001201fed24 s maxtoken +0000000120206c8c b may_move_cost +00000001201ff488 s may_not_optimize +00000001200aef80 T may_trap_p +0000000120016f60 T maybe_build_cleanup +0000000120006ef0 T maybe_building_objc_message_expr +0000000120106830 t maybe_eliminate_biv +00000001201069c0 t maybe_eliminate_biv_1 +0000000120006ec0 T maybe_objc_check_decl +0000000120006ed0 T maybe_objc_comptypes +0000000120006ee0 T maybe_objc_method_name +00000001202000c0 S maybepermanent_firstobj +000000012020bdf0 B maybepermanent_obstack +0000000120190250 t mem100_unit_blockage +000000012018c440 T mem100_unit_blockage_range +0000000120190b80 t mem100_unit_conflict_cost +000000012018c1d0 T mem100_unit_ready_cost +000000012018fca0 t mem110_unit_blockage +000000012018be80 T mem110_unit_blockage_range +000000012018bc10 T mem110_unit_ready_cost +00000001201ff5d0 s mem_last_set +0000000120200568 S memcmp_libfunc +0000000120200520 S memcpy_libfunc +0000000120207540 b memlocs +0000000120093c80 T memory_address +00000001200956f0 T memory_address_noforce +00000001201716e0 T memory_address_p +0000000120173730 T memory_operand +0000000120131600 t memref_referenced_p +0000000120160a20 t memrefs_conflict_p +0000000120200420 S memset_libfunc +00000001200e77c0 t mention_regs +00000001200f5390 t merge_equiv_classes +000000012012cba0 t merge_outer_ops +00000001201ff23c S merror +0000000120200a88 b message.0 +00000001201e740e d message.4 +000000012002d590 T min_precision +00000001201fee04 s missing_braces_mentioned +00000001200cee50 t mod_fund_type_attribute +00000001200cf2c0 t mod_u_d_type_attribute +00000001201e9488 D mode_class +0000000120173e40 T mode_dependent_address_p +0000000120049050 T mode_for_size +00000001201eb3d0 d mode_from_align +0000000120173e50 T mode_independent_operand +00000001201e93a0 D mode_name +00000001201e94fc D mode_size +000000012020bf38 B mode_to_const_map +000000012020bfac B mode_to_load_map +000000012020c094 B mode_to_store_map +00000001201e9570 D mode_unit_size +00000001201e95e4 D mode_wider_mode +000000012014ac70 t modes_equiv_for_class_p +00000001200ad550 T modified_between_p +00000001200ad830 T modified_in_p +00000001201ff340 s modified_mem +00000001201ff338 s modified_regs +00000001202000e0 S momentary_firstobj +00000001202000a8 S momentary_function_firstobj +000000012020bb28 B momentary_obstack +0000000120200118 S momentary_stack +00000001201928e0 T mostly_false_jump +0000000120156f70 t mostly_true_jump +0000000120200618 S mov_optab +0000000120082310 T move_block_from_reg +0000000120082240 T move_block_to_reg +0000000120082c80 t move_by_pieces +0000000120071640 t move_by_pieces_1 +0000000120071540 t move_by_pieces_ninsns +000000012006f470 T move_cleanups_up +0000000120206bc8 b move_cost +000000012012a4e0 t move_deaths +00000001200fef90 t move_movables +0000000120197240 T move_operand +00000001201ff490 s moved_once +000000012020c020 B movstr_optab +00000001202005e8 S movstrict_optab +00000001200bb870 t mtherr +00000001202039c8 b mul_cost +000000012004a0a0 T mul_double +0000000120203b24 b mul_highpart_cost +0000000120203ab0 b mul_widen_cost +00000001201ffbbc s n.3 +00000001202008b0 S n_basic_blocks +0000000120200958 S n_earlyclobbers +00000001201ff428 s n_elements_made +00000001201ff848 s n_memlocs +0000000120200900 S n_non_fixed_regs +00000001201ff668 s n_occurrences +0000000120145880 T n_occurrences +00000001202009a4 S n_regs_saved +00000001201ff830 s n_regs_set +0000000120200954 S n_reloads +00000001201ff844 s n_replacements +00000001201ff8a0 s n_spills +00000001201ff478 s n_times_set +00000001201ff480 s n_times_used +00000001201fed38 s name.2 +00000001201fedb0 s named_labels +00000001200a8700 T named_section +0000000120200388 S nedf2_libfunc +00000001201fefe8 s need_error_newline +0000000120055d70 T neg_double +00000001202005d0 S neg_optab +00000001201ff13c s negate_cost +0000000120093010 T negate_rtx +0000000120200690 S nehf2_libfunc +0000000120200680 S nesf2_libfunc +00000001202002b0 S nesting_depth +00000001202002a0 S nesting_stack +0000000120200350 S netf2_libfunc +00000001201ff8f8 s new_asm_operands_vec +00000001200f5100 t new_basic_block +00000001201feca8 g new_block +000000012016a0d0 t new_insn_dead_notes +000000012014ae20 t new_spill_reg +00000001201fed20 s newline_warning.1 +00000001201ff5ec s newpat_used_regs +00000001202004c8 S nexf2_libfunc +00000001200b4ab0 T next_active_insn +00000001202009a8 S next_block_index +00000001201ff254 s next_block_number +00000001201fec88 g next_block_number +00000001201ff004 s next_decl_uid +00000001200b4920 T next_insn +00000001200b4b90 T next_label +00000001200e6ed0 T next_nondeleted_insn +00000001200b49d0 T next_nonnote_insn +00000001201ff260 s next_pubname_number +00000001201ff35c s next_qty +00000001201ff6b0 s next_qty +00000001200b4a30 T next_real_insn +00000001201fec38 g next_type_uid +00000001201fec8c g next_unused_dienum +00000001201fec08 g nextchar +00000001201ff020 s nlab.0 +00000001201ffbb0 s nlab.0 +0000000120134bb0 t no_conflict_p +00000001201ff7f8 s no_global_alloc_regs +00000001200afdb0 T no_labels_between_p +00000001201ff21c s no_line_numbers +00000001200563a0 T non_lvalue +00000001201734b0 T nonimmediate_operand +00000001201ea570 d nonleaf.1 +00000001202001b0 S nonlocal_goto_handler_slot +0000000120200220 S nonlocal_goto_stack_level +0000000120062ae0 T nonlocal_label_rtx_list +0000000120200268 S nonlocal_labels +0000000120173540 T nonmemory_operand +0000000120123780 t nonzero_bits +00000001201ff638 s nonzero_bits_mode +00000001201ff648 s nonzero_sign_valid +00000001201078e0 t note_addr_stored +00000001201ff4b0 s note_insn +00000001201e9a70 D note_insn_name +00000001201ffa10 s note_list +00000001200f2a60 t note_mem_written +00000001200dfe50 t note_modified_parmregs +00000001200ae350 T note_stores +00000001201ffb80 s nregs +00000001200436a0 T nreverse +00000001201ffdc8 S null_pointer_node +0000000120197c50 T null_prologue +00000001201ffb30 s num_changes +000000012018d780 T num_delay_slots +00000001201ff8d0 s num_eliminable +0000000120209530 b num_filled_delays +0000000120209520 b num_insns_needing_delays +00000001201ff8e8 s num_labels +00000001201ff4a4 s num_mem_sets +00000001201ff4a0 s num_movables +00000001201ff8cc s num_not_at_initial_offset +00000001201ff330 s num_same_regs +00000001201ff510 s num_scratch +0000000120124310 t num_sign_bit_copies +0000000120173000 T num_validated_changes +00000001201ffb84 s nxregs +000000012003ca00 T oballoc +00000001201fef6c S obey_regdecls +0000000120042310 T obfree +00000001200423e0 T object_permanent_p +00000001202000d0 S obstack_stack +0000000120201200 b obstack_stack_obstack +0000000120197a60 T odd_relop +00000001201ff8e0 s offsets_at +00000001201ff8d8 s offsets_known_at +0000000120173b60 T offsettable_address_p +0000000120173a80 T offsettable_memref_p +0000000120173af0 T offsettable_nonstrict_memref_p +00000001201ff8f0 s old_asm_operands_vec +00000001201ffa28 s old_live_regs +0000000120200348 S one_cmpl_optab +0000000120206d50 b op_costs +000000012003b850 t open_dump_file +000000012004b950 T operand_equal_p +00000001200b1df0 T operand_subword +00000001200b41c0 T operand_subword_force +000000012013ce20 T operands_match_p +00000001201ec06c D optab_bit_and_expr +00000001201ec09c D optab_bit_ior_expr +00000001201ec544 D optab_bit_not_expr +00000001201ec0cc D optab_bit_xor_expr +00000001201ec41c D optab_eq_expr +00000001201ec2fc D optab_ge_expr +00000001201ec38c D optab_gt_expr +00000001201ec26c D optab_le_expr +00000001201ec0fc D optab_lshift_expr +00000001201ec1dc D optab_lt_expr +00000001201ebe9c D optab_minus_expr +00000001201ebf0c D optab_mult_expr +00000001201ec48c D optab_ne_expr +00000001201ec4fc D optab_negate_expr +00000001201ebe2c D optab_plus_expr +00000001201ec650 D optab_postdecrement_expr +00000001201ec6b8 D optab_postincrement_expr +00000001201ec580 D optab_predecrement_expr +00000001201ec5e8 D optab_preincrement_expr +00000001201ec02c D optab_rdiv_expr +00000001201ec14c D optab_rshift_expr +00000001201ebf8c D optab_trunc_div_expr +00000001201ebfdc D optab_trunc_mod_expr +00000001201ec19c D optab_truth_and_expr +00000001201ec568 D optab_truth_not_expr +00000001201ec1bc D optab_truth_or_expr +00000001201fec18 G optimize +000000012005c2c0 t optimize_bit_field +0000000120056ff0 t optimize_bit_field_compare +0000000120135250 t optimize_reg_copy_1 +0000000120135790 t optimize_reg_copy_2 +000000012015d5d0 t optimize_skip +000000012014d780 t order_regs_for_reload +00000001201ff2f0 s orig_asm_operands_vector +00000001201ff098 s out_arg_offset +00000001201eb388 d out_rcs_id +00000001202001b8 S outer_function_chain +00000001201ff1c0 s outfile +000000012017d430 t output_107 +000000012017d460 t output_108 +000000012017d1b0 t output_11 +000000012017d490 t output_114 +000000012017d4c0 t output_117 +000000012017d230 t output_12 +000000012017d4f0 t output_120 +000000012017d520 t output_121 +000000012017d550 t output_123 +000000012017d580 t output_126 +000000012017d5b0 t output_127 +000000012017d5e0 t output_129 +000000012017d610 t output_131 +000000012017d640 t output_132 +000000012017d670 t output_134 +000000012017d6a0 t output_147 +000000012017d6d0 t output_149 +000000012017d700 t output_151 +000000012017d730 t output_154 +000000012017d760 t output_156 +000000012017d790 t output_158 +000000012017d7c0 t output_169 +000000012017d7f0 t output_223 +000000012017d820 t output_225 +000000012017d960 t output_228 +000000012017d990 t output_230 +000000012017dad0 t output_233 +000000012017db00 t output_235 +000000012017dc40 t output_245 +000000012017dc70 t output_247 +000000012017dca0 t output_249 +000000012017dcd0 t output_252 +000000012017dd00 t output_254 +000000012017dd70 t output_256 +000000012017dde0 t output_257 +000000012017de50 t output_258 +000000012017dec0 t output_259 +000000012017dfb0 t output_261 +000000012017dfe0 t output_262 +000000012017e010 t output_264 +000000012017e040 t output_269 +000000012017e080 t output_271 +000000012017e0b0 t output_273 +000000012017e0e0 t output_281 +000000012017d2b0 t output_46 +000000012017d380 t output_58 +000000012017d3b0 t output_61 +000000012017d3e0 t output_94 +000000012016edc0 T output_addr_const +000000012016ed70 T output_address +00000001200a7340 t output_addressed_constants +0000000120196ed0 T output_and +00000001200cf650 t output_array_type_die +00000001201941b0 T output_ascii +000000012016e3b0 T output_asm_insn +000000012016ebc0 T output_asm_label +00000001200d6fa0 t output_block +0000000120198690 T output_block_profiler +00000001200d9460 t output_bound_representation +00000001201fef50 S output_bytecode +0000000120192610 T output_call +00000001200d3530 t output_compile_unit_die +00000001200a74b0 T output_constant +00000001200a5ff0 T output_constant_def +00000001200a6550 t output_constant_def_contents +00000001200a6ff0 T output_constant_pool +00000001200a79b0 t output_constructor +00000001200ca140 t output_decl +00000001200c9f60 t output_decls_for_scope +00000001200a94c0 T output_deferred_addressed_constants +0000000120164770 T output_dependence +00000001200d6db0 t output_die +00000001200d98c0 t output_enumeral_list +00000001200d0550 t output_enumeration_type_die +0000000120039010 T output_file_directive +0000000120192b90 T output_file_start +00000001200d0ad0 t output_formal_parameter_die +00000001201982d0 T output_function_block_profiler +0000000120195060 T output_function_profiler +00000001200d0f40 t output_global_subroutine_die +00000001200d1b20 t output_global_variable_die +0000000120026240 t output_init_element +00000001200df520 T output_inline_function +00000001200cfef0 t output_inlined_enumeration_type_die +00000001200d0110 t output_inlined_structure_type_die +00000001200d8fb0 t output_inlined_subroutine_die +00000001200d0330 t output_inlined_union_type_die +0000000120196f90 T output_ior +0000000120197be0 T output_label +00000001200d2050 t output_label_die +00000001200d8b40 t output_lexical_block_die +0000000120196c00 T output_load_const_dimode +0000000120196b00 T output_load_const_double +0000000120196a80 T output_load_const_float +0000000120196990 T output_load_const_int +00000001200d4cd0 t output_local_subroutine_die +00000001200d2540 t output_local_variable_die +00000001200c8e30 t output_mem_loc_descriptor +00000001200d2a60 t output_member_die +000000012016ecd0 t output_operand +000000012016f9b0 T output_operand_lossage +00000001200d6d60 t output_padded_null_die +0000000120023cd0 t output_pending_init_elements +00000001200d2fd0 t output_ptr_to_mbr_type_die +0000000120038f10 T output_quoted_string +00000001201ff86c s output_reloadnum +00000001200cfaa0 t output_set_type_die +000000012016e090 t output_source_line +00000001200d43b0 t output_string_type_die +00000001200d46e0 t output_structure_type_die +00000001200d58b0 t output_subroutine_type_die +00000001200c97e0 t output_type +00000001200d5e50 t output_typedef_die +00000001200d6370 t output_union_type_die +00000001200d6960 t output_unspecified_parameters_die +0000000120197020 T output_xor +000000012002cda0 T overflow_warning +00000001201febf8 g p.0 +000000012005ec10 t pad_below +000000012005eb40 t pad_to_arg_alignment +00000001201ff040 s parm_birth_insn +00000001201ff058 s parm_reg_stack_loc +00000001201ff2e0 s parmdecl_map +0000000120017070 T parmlist_tags_warning +000000012020006c S parse_time +000000012001bc20 T parser_build_binary_op +0000000120197960 T partial_ccmode_register_operand +00000001201eb678 d patterns.3 +0000000120197bc0 T pc_or_label_ref +0000000120200770 S pc_rtx +00000001201fef64 S pedantic +000000012001f1f0 t pedantic_lvalue_warning +0000000120200150 S pedantic_lvalues +0000000120056480 T pedantic_non_lvalue +0000000120031860 T pedwarn +0000000120021cf0 T pedwarn_init +0000000120031df0 T pedwarn_with_decl +0000000120032230 T pedwarn_with_file_and_line +00000001202156c8 B peep_operand +0000000120156270 T peephole +00000001201ffb10 s pending_blocks +00000001201ff110 s pending_chain +00000001201ff988 s pending_dead_regs +00000001201ffdd8 S pending_invalid_xref +00000001201ffdb8 S pending_invalid_xref_file +00000001201ffc60 S pending_invalid_xref_line +00000001201ffa78 s pending_lists_length +00000001201ffa58 s pending_read_insns +00000001201ffa60 s pending_read_mems +00000001201ff298 s pending_sibling_stack +00000001201ff2a0 s pending_siblings +00000001201ff2a4 s pending_siblings_allocated +00000001201ff018 s pending_sizes +00000001202002e0 S pending_stack_adjust +00000001201ff2b4 s pending_types +00000001201ff2b0 s pending_types_allocated +00000001201ff2a8 s pending_types_list +00000001201ffa68 s pending_write_insns +00000001201ffa70 s pending_write_mems +0000000120016e60 T pending_xref_error +000000012003cbe0 T perm_calloc +0000000120043860 T perm_tree_cons +000000012003caf0 T permalloc +000000012003c480 T permanent_allocation +000000012020bd98 B permanent_obstack +00000001200386e0 T pfatal_with_name +0000000120198a50 T pic_address_needs_scratch +0000000120200768 S pic_offset_table_rtx +0000000120039510 t pipe_closed +00000001201ff0f0 s placeholder_list.0 +00000001200c0440 t plain_type_1 +00000001200952f0 T plus_constant_for_output_wide +0000000120093810 T plus_constant_wide +000000012001e270 t pointer_diff +000000012001deb0 t pointer_int_sum +00000001201ff1a0 s pool_offset +0000000120017b10 T pop_c_function_context +0000000120038df0 T pop_float_handler +0000000120061c90 T pop_function_context +00000001200596f0 T pop_function_context_from +0000000120023580 T pop_init_level +000000012002f420 T pop_iterator_stack +000000012000d3d0 T pop_label_level +00000001200424e0 T pop_momentary +0000000120042570 T pop_momentary_nofree +0000000120042200 T pop_obstacks +0000000120062100 T pop_temp_slots +00000001200b63b0 T pop_topmost_sequence +000000012000cfb0 T poplevel +000000012000b9c0 T position_after_white_space +000000012014a6a0 t possible_group_p +0000000120134a40 t post_mark_life +0000000120161fb0 t potential_hazard +0000000120207ed0 b potential_reload_regs +0000000120109670 t precondition_loop_p +000000012007e2d0 t preexpand_calls +00000001201ff690 s prefclass +000000012019dce0 T preferred_typecode +00000001201fece8 s prefix_attributes +0000000120089940 T prepare_call_address +0000000120164c60 t prepare_unit +00000001201001f0 t prescan_loop +000000012003c6b0 T preserve_data +000000012003c790 T preserve_initializer +0000000120042420 T preserve_momentary +0000000120194ca0 t preserve_registers +0000000120061f10 T preserve_rtl_expr_result +000000012006f0c0 T preserve_subexpressions_p +000000012005a270 T preserve_temp_slots +00000001200b4b20 T prev_active_insn +00000001201fec94 g prev_file_entry_num.1 +00000001201ff3a0 s prev_insn +00000001200b4bc0 T prev_label +00000001201fecd8 g prev_lineno.1 +00000001200b4a00 T prev_nonnote_insn +00000001200b4a70 T prev_real_insn +00000001200b4970 T previous_insn +00000001201ff600 s previous_num_undos +00000001201ff280 s primary_filename +00000001201e7428 d print_char_table +00000001201fec28 G print_error_function +00000001200162f0 T print_lang_decl +0000000120016310 T print_lang_identifier +0000000120006e90 T print_lang_statistics +0000000120016300 T print_lang_type +00000001200458e0 T print_node +0000000120045560 T print_node_brief +000000012003cde0 T print_obstack_name +0000000120045470 T print_obstack_statistics +0000000120195a90 T print_operand +0000000120196430 T print_operand_address +00000001200ad020 T print_rtl +00000001200ac610 t print_rtx +0000000120038150 t print_switch_values +0000000120038570 T print_time +0000000120162160 t priority +00000001200240c0 T process_init_element +0000000120105c10 t product_cheap_p +00000001201fffec S profile_block_flag +00000001201fef60 S profile_flag +00000001202009b0 S profile_label_no +00000001201ffec0 S progname +00000001201ff0a0 s prologue +00000001201ffb98 s prologue_marked +0000000120095b10 T promote_mode +000000012010ff70 t propagate_block +0000000120070290 T protect_from_queue +00000001201377f0 t prune_preferences +00000001202006f0 S ptr_mode +00000001201ffcd0 S ptr_type_node +00000001201ffbd0 s ptrconsts +00000001201ffc58 S ptrdiff_type_node +00000001200434e0 T purpose_member +0000000120082740 T push_block +0000000120017a20 T push_c_function_context +0000000120038d60 T push_float_handler +0000000120061c70 T push_function_context +00000001200593c0 T push_function_context_to +0000000120022dd0 T push_init_level +000000012002ec40 T push_iterator_stack +0000000120016830 T push_label_level +000000012003d050 T push_momentary +000000012003c210 T push_obstacks +000000012003c360 T push_obstacks_nochange +00000001201736d0 T push_operand +0000000120016f70 T push_parm_decl +000000012013a430 t push_reload +0000000120145fe0 t push_secondary_reload +00000001200620e0 T push_temp_slots +00000001200b6220 T push_to_sequence +00000001200b62f0 T push_topmost_sequence +00000001200697b0 T pushcase +0000000120069ba0 T pushcase_range +000000012000d580 T pushdecl +00000001200169a0 T pushdecl_top_level +00000001200165f0 T pushlevel +00000001200168c0 T pushtag +0000000120048eb0 T put_pending_sizes +000000012005a830 t put_reg_into_stack +000000012005a5a0 T put_var_into_stack +00000001201ffba0 s pwd.0 +00000001201ff990 s q_ptr +00000001201ff994 s q_size +00000001201ff718 s qty_alternate_class +00000001201ff6f0 s qty_birth +00000001201ff728 s qty_changes_size +00000001201331b0 t qty_compare +0000000120135d80 t qty_compare_1 +00000001201ff388 s qty_comparison_code +00000001201ff390 s qty_comparison_const +00000001201ff398 s qty_comparison_qty +00000001201ff378 s qty_const +00000001201ff380 s qty_const_insn +00000001201ff6f8 s qty_death +00000001201ff360 s qty_first_reg +00000001201ff730 s qty_first_reg +00000001201ff368 s qty_last_reg +00000001201ff6e8 s qty_min_class +00000001201ff370 s qty_mode +00000001201ff708 s qty_mode +00000001201ff710 s qty_n_calls_crossed +00000001201ff6e0 s qty_n_refs +00000001201ff6c0 s qty_phys_copy_sugg +00000001201ff6d0 s qty_phys_num_copy_sugg +00000001201ff6d8 s qty_phys_num_sugg +00000001201ff6b8 s qty_phys_reg +00000001201ff6c8 s qty_phys_sugg +00000001201ff720 s qty_scratch_rtx +00000001201ff700 s qty_size +0000000120133350 t qty_sugg_compare +0000000120135b10 t qty_sugg_compare_1 +0000000120082bb0 t queued_subexp_p +00000001201fef70 S quiet_flag +0000000120058ff0 t range_test +00000001201690b0 t rank_for_schedule +0000000120205f6e b rbit +00000001201eb0d8 d rcs_id.0 +00000001201ff234 s re +0000000120164430 T read_dependence +00000001200ab100 T read_rtx +00000001200aaf00 T read_skip_spaces +000000012000bd20 t readescape +00000001200a8640 T readonly_data_section +000000012001f260 T readonly_warning +0000000120043160 T real_onep +00000001201978b0 T real_or_0_operand +0000000120197080 T real_power_of_2_operand +00000001200432e0 T real_twop +0000000120042870 T real_value_from_int_cst +0000000120056130 T real_value_truncate +0000000120043080 T real_zerop +0000000120043460 T really_constant_p +00000001200328e0 T really_sorry +00000001200229e0 T really_start_incremental_init +00000001201ff230 s rebit +000000012017a390 T recog +00000001201743e0 T recog_1 +0000000120174bf0 T recog_2 +0000000120175520 T recog_3 +0000000120175ca0 T recog_4 +0000000120176f90 T recog_5 +00000001201792d0 T recog_6 +0000000120215768 B recog_dup_loc +00000001202009d8 S recog_dup_num +00000001201260e0 t recog_for_combine +0000000120172e50 T recog_memoized +0000000120215718 B recog_operand +0000000120215778 B recog_operand_loc +0000000120006f00 T recognize_objc_keyword +000000012012f5f0 t record_address_regs +0000000120103860 t record_biv +0000000120138d10 t record_conflicts +00000001200aa180 t record_constant +00000001200a5640 t record_constant_1 +00000001200aa490 t record_constant_rtx +00000001201295b0 t record_dead_and_set_regs +000000012012cf60 t record_dead_and_set_regs_1 +00000001201ff670 s record_dead_insn +00000001200fdd00 T record_excess_regs +000000012002b190 T record_function_format +0000000120103a90 t record_giv +0000000120107a90 t record_initial +00000001200f1b10 t record_jump_cond +000000012013a2d0 t record_one_conflict +000000012012e7c0 t record_reg_classes +00000001201290e0 t record_value_for_reg +00000001201ff410 s recorded_label_ref +000000012000dfc0 t redeclaration_error_message +00000001200e4ec0 T redirect_exp +00000001200e7000 T redirect_jump +00000001200e5150 t redirect_tablejump +0000000120157570 t redundant_insn +0000000120143e80 T refers_to_mem_for_reload_p +00000001200e9f90 t refers_to_mem_p +00000001200e99e0 t refers_to_p +0000000120143900 T refers_to_regno_for_reload_p +00000001200adaa0 T refers_to_regno_p +00000001201ea138 D reg_alloc_order +00000001201ff790 s reg_allocno +0000000120130460 T reg_alternate_class +00000001202008b8 S reg_basic_block +000000012012ab60 t reg_bitfield_target_p +0000000120200870 S reg_biv_class +00000001202008d0 S reg_changes_size +0000000120213bb4 B reg_class_contents +00000001201ea6e8 d reg_class_names +00000001201ea7c8 d reg_class_names.0 +00000001201ea068 d reg_class_names.1 +0000000120213c2c B reg_class_size +00000001202137e8 B reg_class_subclasses +0000000120130720 T reg_class_subset_p +0000000120213af0 B reg_class_subunion +0000000120213c48 B reg_class_superclasses +00000001202138ac B reg_class_superunion +000000012012fde0 T reg_classes_intersect_p +000000012010d990 t reg_dead_after_loop +0000000120129fa0 t reg_dead_at_p +000000012012d120 t reg_dead_at_p_1 +00000001201ff67c s reg_dead_endregno +00000001201ff680 s reg_dead_flag +00000001201ff678 s reg_dead_regno +00000001201ea720 d reg_eliminate +0000000120200988 S reg_equiv_address +0000000120200990 S reg_equiv_constant +00000001201ff898 s reg_equiv_init +0000000120200970 S reg_equiv_mem +0000000120200968 S reg_equiv_memory_loc +0000000120173e80 T reg_fits_class_p +00000001201ff880 s reg_has_output_reload +00000001200fdf70 t reg_in_basic_block_p +00000001201ff3d0 s reg_in_table +0000000120133f10 t reg_is_born +00000001201ff888 s reg_is_output_reload +0000000120135f50 t reg_is_set +0000000120200828 S reg_iv_info +0000000120200838 S reg_iv_type +00000001201ffa48 s reg_known_equiv_p +00000001201ffa40 s reg_known_value +00000001201ffa50 s reg_known_value_size +00000001201ff5c0 s reg_last_death +00000001201ff878 s reg_last_reload_reg +00000001201ff5c8 s reg_last_set +00000001201ff620 s reg_last_set_invalid +00000001201ff610 s reg_last_set_label +00000001201ff650 s reg_last_set_mode +00000001201ff658 s reg_last_set_nonzero_bits +00000001201ff660 s reg_last_set_sign_bit_copies +00000001201ff618 s reg_last_set_table_tick +00000001201ff608 s reg_last_set_value +00000001201ff9b8 s reg_last_sets +00000001201ff9b0 s reg_last_uses +0000000120200888 S reg_live_length +00000001201ff2c8 s reg_map +00000001201ff890 s reg_max_ref_width +00000001201ff7b0 s reg_may_share +0000000120133d40 t reg_meets_class_p +00000001200ad0f0 T reg_mentioned_p +0000000120200898 S reg_n_calls_crossed +0000000120200890 S reg_n_deaths +00000001202008c0 S reg_n_refs +0000000120200918 S reg_n_sets +00000001201ea270 D reg_names +00000001201ff3b8 s reg_next_eqv +00000001201ff738 s reg_next_in_qty +00000001201ff518 s reg_next_use +00000001201ff630 s reg_nonzero_bits +00000001201e9ae0 D reg_note_name +00000001201ff748 s reg_offset +00000001201974e0 T reg_or_0_operand +0000000120197820 T reg_or_bbx_mask_operand +00000001201ff570 s reg_order +0000000120143cd0 T reg_overlap_mentioned_for_reload_p +00000001200ade60 T reg_overlap_mentioned_p +00000001201ff9c0 s reg_pending_sets +00000001201ff9c8 s reg_pending_sets_all +0000000120130430 T reg_preferred_class +00000001201ff3c0 s reg_prev_eqv +00000001201ff3b0 s reg_qty +00000001201ff740 s reg_qty +0000000120213970 B reg_raw_mode +00000001200aff00 T reg_referenced_between_p +00000001200ad320 T reg_referenced_p +00000001202076d0 b reg_reloaded_contents +00000001202077d0 b reg_reloaded_insn +0000000120200940 S reg_renumber +00000001202091b0 b reg_restore_code +00000001201fec48 G reg_rtx_no +0000000120208eb0 b reg_save_code +00000001201304c0 T reg_scan +000000012012f920 t reg_scan_mark_refs +00000001200afff0 T reg_set_between_p +00000001201ff1d0 s reg_set_flag +00000001200b0600 T reg_set_last +00000001200b0d20 t reg_set_last_1 +00000001201ff1e0 s reg_set_last_first_regno +00000001201ff1e4 s reg_set_last_last_regno +00000001201ff1d4 s reg_set_last_unknown +00000001201ff1d8 s reg_set_last_value +00000001200b0140 T reg_set_p +00000001200b0cc0 t reg_set_p_1 +00000001201ff1c8 s reg_set_reg +00000001201ff640 s reg_sign_bit_copies +00000001201ff3c8 s reg_tick +00000001200afdf0 T reg_used_between_p +00000001201ff568 s reg_where_born +00000001201ff560 s reg_where_dead +000000012012db20 T regclass +00000001201304a0 T regclass_init +00000001201731f0 T register_operand +0000000120112800 T regno_clobbered_at_setjmp +0000000120145180 T regno_clobbered_p +00000001202008f0 S regno_first_uid +00000001202008f8 S regno_last_note_uid +0000000120200908 S regno_last_uid +0000000120200738 S regno_pointer_flag +00000001202006f8 S regno_pointer_flag_length +0000000120200760 S regno_reg_rtx +00000001202088b0 b regno_save_mem +00000001202085b0 b regno_save_mode +0000000120112780 T regno_uninitialized +000000012016ac40 t regno_use_in +00000001201ff580 s regs_change_size +00000001202156d8 B regs_ever_live +0000000120207f50 b regs_explicitly_used +00000001201ff3e0 s regs_invalidated_by_call +00000001201ff578 s regs_live +00000001201ff750 s regs_live +00000001201ff758 s regs_live_at +00000001202008e0 S regs_live_at_setjmp +00000001202008a8 S regs_may_share +00000001201ff828 s regs_set +00000001201ff7f0 s regs_someone_prefers +00000001201ff800 s regs_used_so_far +00000001202008a0 S regset_bytes +00000001202008e8 S regset_size +00000001200e8e90 t rehash_using_reg +000000012000b8f0 T reinit_parse_for_function +000000012015ba10 t relax_delay_slots +0000000120147750 T reload +000000012014db60 t reload_as_needed +00000001202009d0 S reload_completed +0000000120214818 B reload_earlyclobbers +0000000120200960 S reload_first_uid +0000000120200980 S reload_firstobj +0000000120214200 B reload_in +0000000120215580 B reload_in_optab +00000001201ff870 S reload_in_progress +0000000120214e08 B reload_in_reg +0000000120214868 B reload_inc +00000001202153a0 B reload_inheritance_insn +0000000120214fe8 B reload_inherited +00000001202143e0 B reload_inmode +0000000120208290 b reload_mode +000000012020095c S reload_n_operands +00000001202147dc B reload_nocombine +0000000120208380 b reload_nregs +00000001202155f8 B reload_obstack +00000001202144d0 B reload_opnum +00000001202146b0 B reload_optional +0000000120215650 B reload_order +0000000120213e40 B reload_out +0000000120215024 B reload_out_optab +0000000120214020 B reload_outmode +00000001202151c0 B reload_override_in +0000000120214b38 B reload_reg_class +0000000120152d80 t reload_reg_class_lower +00000001201537f0 t reload_reg_free_before_p +00000001201531c0 t reload_reg_free_p +0000000120153c50 t reload_reg_reaches_end_p +0000000120214c28 B reload_reg_rtx +00000001201ff900 s reload_reg_used +00000001201ff928 s reload_reg_used_at_all +00000001201ff930 s reload_reg_used_for_inherit +0000000120208510 b reload_reg_used_in_input +0000000120208470 b reload_reg_used_in_input_addr +00000001201ff918 s reload_reg_used_in_insn +00000001201ff908 s reload_reg_used_in_op_addr +00000001201ff910 s reload_reg_used_in_op_addr_reload +00000001201ff920 s reload_reg_used_in_other_addr +0000000120208560 b reload_reg_used_in_output +00000001202084c0 b reload_reg_used_in_output_addr +0000000120214a48 B reload_secondary_in_icode +00000001202146ec B reload_secondary_in_reload +0000000120214958 B reload_secondary_out_icode +0000000120213d50 B reload_secondary_out_reload +0000000120214110 B reload_secondary_p +00000001202150d0 B reload_spill_index +00000001202145c0 B reload_when_needed +00000001201ea6a0 d reload_when_needed_name +000000012014e650 t reloads_conflict +00000001201979e0 T relop +0000000120197ac0 T relop_no_unsigned +000000012010cb90 t remap_split_bivs +000000012006f3d0 T remember_end_note +000000012000b820 T remember_protocol_qualifiers +000000012012be00 T remove_death +00000001200f5250 t remove_from_table +00000001200e8db0 t remove_invalid_refs +00000001200b0b00 T remove_note +000000012005f400 T reorder_blocks +00000001200b4cd0 T reorder_insns +00000001200b4d70 T reorder_insns_with_line_notes +00000001201ff97c s reorg_pass_number +00000001201581f0 t reorg_redirect_jump +00000001200af410 T replace_regs +00000001201ff840 s replace_reloads +00000001200b0b70 T replace_rtx +0000000120207090 b replacements +00000001200389c0 T report_error_function +00000001200617b0 T reposition_prologue_and_epilogue_notes +0000000120024f80 T require_complete_type +00000001201fee8c s require_constant_elements +00000001201fee88 s require_constant_value +0000000120134d50 t requires_inout +00000001200b27e0 T reset_used_flags +0000000120032ef0 T rest_of_compilation +0000000120032a40 T rest_of_decl_compilation +00000001200390c0 T rest_of_type_compilation +00000001200df230 t restore_constants +00000001200b4580 T restore_emit_status +0000000120082170 T restore_expr_status +0000000120200250 S restore_machine_status +0000000120155ac0 t restore_referenced_regs +00000001200b31a0 T restore_reg_data +00000001200b32b0 t restore_reg_data_1 +000000012006e3a0 T restore_stmt_status +00000001200495c0 T restore_storage_status +000000012003c060 T restore_tree_status +00000001200a9670 T restore_varasm_status +000000012018abe0 T result_ready_cost +00000001200425d0 T resume_momentary +0000000120042190 T resume_temporary_allocation +0000000120139db0 T retry_global_alloc +00000001202001a0 S return_label +00000001200b4280 T reverse_comparison +00000001200e3c20 T reverse_condition +00000001201ffb74 s reversep.1 +0000000120128fd0 t reversible_comparison_p +000000012020b920 B ridpointers +00000001201fec5c g rlast +00000001201ff22e s rmbit +00000001201ff22c s rmsk +00000001201fec58 G rndprc +00000001200cecf0 t root_type +0000000120200308 S rotl_optab +0000000120200600 S rotr_optab +0000000120095c80 T round_push +000000012005f1b0 t round_trampoline_addr +00000001200490d0 T round_up +0000000120056050 T rrotate_double +0000000120055ea0 T rshift_double +00000001201feef8 S rtl_dump +00000001201feefc S rtl_dump_and_exit +00000001201fffe0 S rtl_dump_file +0000000120200190 S rtl_expr_chain +00000001200422d0 T rtl_in_current_obstack +00000001200422f0 T rtl_in_saveable_obstack +00000001202000e8 S rtl_obstack +00000001200aa6a0 T rtvec_alloc +00000001200af9c0 T rtx_addr_can_trap_p +00000001200afad0 T rtx_addr_varies_p +00000001200ac4c0 T rtx_alloc +00000001201e99f8 D rtx_class +00000001200e7360 T rtx_cost +00000001200fe8c0 t rtx_equal_for_loop_p +00000001201604d0 t rtx_equal_for_memref_p +00000001200e6340 T rtx_equal_for_thread_p +00000001202006ec S rtx_equal_function_value_matters +00000001200ae090 T rtx_equal_p +00000001201e9658 D rtx_format +00000001200ac5a0 T rtx_free +0000000120213340 B rtx_length +00000001201e9000 D rtx_name +00000001200e5350 T rtx_renumbered_equal_p +00000001200960d0 T rtx_to_tree_code +00000001200af710 T rtx_unstable_p +00000001200af860 T rtx_varies_p +00000001201ff228 s rw +00000001201458d0 T safe_from_earlyclobber +0000000120074f60 t safe_from_p +00000001200e93d0 t safe_hash +00000001201ff328 s same_regs +00000001201fff58 S save_argc +00000001201fff50 S save_argv +0000000120155370 T save_call_clobbered_regs +00000001200db2e0 t save_constants +00000001200b44e0 T save_emit_status +0000000120043d00 T save_expr +0000000120200260 S save_expr_regs +00000001200820a0 T save_expr_status +00000001201feef0 s save_exprs +00000001200da5d0 T save_for_inline_copying +00000001200db060 T save_for_inline_nocopy +0000000120200278 S save_machine_status +0000000120083fb0 t save_noncopied_parts +0000000120209d78 b save_regs +000000012006e2e0 T save_stmt_status +00000001200495b0 T save_storage_status +000000012003bdd0 T save_tree_status +00000001200a9620 T save_varasm_status +00000001200421d0 T saveable_allocation +00000001202000f8 S saveable_obstack +0000000120043900 T saveable_tree_cons +000000012003ccf0 T savealloc +00000001201ff100 s saveregs_value +00000001201ff1b0 s sawclose +00000001201ffb60 s sb_high +00000001201ffb68 s sb_low +00000001201ffb58 s sb_name +00000001201ffad8 s sbb_head +00000001201ffae0 s sbb_label_num +00000001201fecc0 g sbb_tail +00000001201e7768 d scan_char_table +00000001200fc970 t scan_loop +000000012014d5a0 t scan_paradoxical_subregs +00000001201fef24 S sched2_dump +00000001201fff80 S sched2_dump_file +00000001201fff78 S sched2_time +00000001201689d0 t sched_analyze +0000000120165080 t sched_analyze_1 +0000000120162450 t sched_analyze_2 +000000012016a620 t sched_analyze_insn +00000001201ffaa0 s sched_before_next_call +00000001201fef18 S sched_dump +00000001201fff30 S sched_dump_file +0000000120168d80 t sched_note_set +00000001201ff9a8 s sched_reg_live_length +00000001201ff9a0 s sched_reg_n_calls_crossed +00000001201ff998 s sched_reg_n_deaths +00000001201fffa8 S sched_time +0000000120165a80 t schedule_block +0000000120169250 t schedule_insn +00000001201631a0 T schedule_insns +0000000120169560 t schedule_select +000000012016a480 t schedule_unit +0000000120200938 S scratch_block +00000001201ff760 s scratch_index +0000000120200948 S scratch_list +0000000120200950 S scratch_list_length +0000000120173270 T scratch_operand +00000001200a8380 T sdata_section +00000001201fec80 G sdb_begin_function_line +00000001202064f8 b sdb_dims +00000001201ff24c s sdb_n_dims +00000001201fec84 g sdb_type_size +00000001200c4ef0 T sdbout_begin_block +00000001200c5510 T sdbout_begin_function +00000001200c6170 t sdbout_block +00000001200c52e0 T sdbout_end_block +00000001200c5a10 T sdbout_end_epilogue +00000001200c5770 T sdbout_end_function +00000001200c6070 T sdbout_init +00000001200c5c90 T sdbout_label +00000001200c6150 T sdbout_mark_begin_function +00000001200c2ea0 t sdbout_one_type +00000001200c66d0 t sdbout_parms +00000001200c2e50 t sdbout_queue_anonymous_type +00000001200c7cb0 t sdbout_reg_parms +00000001200c0a30 T sdbout_symbol +00000001200c25d0 T sdbout_toplevel_data +00000001200c6250 t sdbout_type +00000001200c6080 T sdbout_types +00000001202006a0 S sdiv_optab +00000001201ff130 s sdiv_pow2_cheap +0000000120200610 S sdivmod_optab +00000001201ffbb4 s section +000000012019ced0 t seg_defsym +000000012019d0e0 t seg_refsym +0000000120019cb0 T self_promoting_args_p +0000000120019d90 t self_promoting_type_p +00000001201ff220 s sequence_element_free_list +0000000120205f28 b sequence_result +00000001201ff1f8 S sequence_rtl_expr +0000000120200728 S sequence_stack +00000001201ffb70 s sequencep.0 +00000001201ff010 S set_alignment +0000000120016810 T set_block +00000001200e0010 t set_block_abstract_flags +00000001200dfec0 t set_block_origin_self +00000001200df9e0 T set_decl_abstract_flags +00000001200dffa0 t set_decl_origin_self +0000000120038d10 T set_float_handler +0000000120042790 T set_identifier_size +0000000120025950 T set_init_index +0000000120025b30 T set_init_label +000000012014b7f0 t set_label_offsets +00000001200b4870 T set_last_insn +00000001200b4490 T set_new_first_and_last_insn +00000001200b44b0 T set_new_first_and_last_label_num +00000001200e9ba0 t set_nonvarying_address_components +000000012012bf70 t set_nonzero_bits_and_sign_copies +0000000120139550 t set_preference +0000000120156150 t set_reg_live +0000000120037fe0 T set_target_switch +000000012000bba0 T set_yydebug +0000000120213170 B setcc_gen_code +0000000120063180 T setjmp_args_warning +0000000120063220 T setjmp_protect +00000001200632e0 T setjmp_protect_args +00000001200e6eb0 T sets_cc0_p +00000001201143f0 t setup_incoming_promotions +0000000120154f30 T setup_save_areas +0000000120016d60 T shadow_label +0000000120016ed0 T shadow_tag +0000000120010760 T shadow_tag_warned +00000001201fedb8 s shadowed_labels +0000000120203848 b shift_cost +00000001202038c8 b shiftadd_cost +0000000120203948 b shiftsub_cost +00000001201ffd38 S short_integer_type_node +00000001201ffd70 S short_unsigned_type_node +00000001201fffd8 S shorten_branch_time +000000012016c150 T shorten_branches +000000012002b730 T shorten_compare +00000001200aedf0 T side_effects_p +00000001200a0bc0 T sign_expand_binop +00000001201ffdf0 S signed_char_type_node +00000001200e6b20 T signed_condition +000000012020ada0 b signed_mode_to_code_map +00000001200251f0 T signed_or_unsigned_type +00000001200250e0 T signed_type +00000001201ffcc0 S signed_wchar_type_node +00000001200bd3a0 T significand_size +0000000120040f40 T simple_cst_equal +0000000120044bb0 T simple_cst_list_equal +00000001200e6c70 T simplejump_p +0000000120123360 t simplify_and_const_int +00000001200eaff0 T simplify_binary_operation +0000000120126f90 t simplify_comparison +0000000120104be0 t simplify_giv_expr +000000012011b950 t simplify_if_then_else +000000012011d980 t simplify_logical +00000001200ecbf0 t simplify_plus_minus +00000001200ed5c0 T simplify_relational_operation +0000000120119230 t simplify_rtx +000000012011cb90 t simplify_set +0000000120124b80 t simplify_shift_const +00000001200a96c0 T simplify_subtraction +00000001200ee0b0 T simplify_ternary_operation +00000001200ea450 T simplify_unary_operation +00000001202004e0 S sin_optab +00000001200b0230 T single_set +00000001201fec40 g size.1 +00000001201fec44 g size.2 +00000001201fec14 g size.3 +00000001200562a0 T size_binop +00000001202006e0 S size_directive_output +0000000120043950 T size_in_bytes +000000012004b850 T size_int +0000000120200138 S size_one_node +00000001202031e0 b size_table.0 +0000000120200130 S size_zero_node +0000000120200140 S sizetype +00000001200fe130 t skip_consec_insns +000000012000bbc0 t skip_white_space +00000001201ff43c s skipped_writes_memory +0000000120200410 S smax_optab +0000000120200558 S smin_optab +00000001202004b0 S smod_optab +00000001201ff134 s smod_pow2_cheap +00000001202004a8 S smul_highpart_optab +0000000120200660 S smul_optab +0000000120200540 S smul_widen_optab +0000000120032770 T sorry +00000001201fef4c S sorrycount +00000001201fec7c g source_label_number +00000001201e9d60 D spaces +00000001201fee08 s spelling +00000001201fee10 s spelling_base +00000001201fee18 s spelling_size +000000012014ada0 t spill_failure +000000012014d130 t spill_hard_reg +00000001201ff8c8 s spill_indirect_levels +0000000120207dd0 b spill_reg_order +00000001202079d0 b spill_reg_rtx +0000000120207bd0 b spill_reg_store +0000000120207e50 b spill_regs +0000000120207f90 b spill_stack_slot +0000000120208190 b spill_stack_slot_width +000000012017ab80 T split_1 +000000012016f4e0 T split_double +0000000120169db0 t split_hard_reg_notes +000000012017bb60 T split_insns +0000000120056580 t split_tree +00000001201ff4c8 s splittable_regs +00000001201ff4d0 s splittable_regs_updates +0000000120205fd0 b sqrndbit +0000000120200550 S sqrt_optab +00000001200e31d0 T squeeze_notes +00000001200957d0 T stabilize +000000012003f560 T stabilize_reference +000000012003fa50 T stabilize_reference_1 +00000001202002f0 S stack_arg_under_construction +00000001202002b8 S stack_block_stack +00000001202001f4 S stack_depth +0000000120200748 S stack_pointer_rtx +00000001201fef34 S stack_reg_dump +00000001201fff00 S stack_reg_dump_file +00000001201ffedc S stack_reg_time +0000000120200238 S stack_slot_list +00000001201ff118 s stack_usage_map +00000001201e8968 D standard_tree_code_length +00000001201e8b60 D standard_tree_code_name +00000001201e8578 D standard_tree_code_type +0000000120010a80 T start_decl +00000001200177b0 T start_enum +0000000120014be0 T start_function +0000000120042770 T start_identifier_warnings +0000000120022750 T start_init +0000000120209508 b start_of_epilogue_needs +00000001200b60d0 T start_sequence +00000001200b6170 T start_sequence_for_rtl_expr +00000001200174a0 T start_struct +00000001201fed30 s state.0 +0000000120200710 S static_chain_incoming_rtx +0000000120200778 S static_chain_rtx +00000001201ffe28 S static_ctors +00000001201ffc68 S static_dtors +00000001201ff860 s static_reload_reg_p +0000000120043bf0 T staticp +000000012015feb0 t steal_delay_list_from_fallthrough +000000012015f680 t steal_delay_list_from_target +00000001201fecf0 s stmt_count +00000001201ff088 s stmt_expr_depth +000000012020bee0 B stmt_obstack +000000012008a440 T store_bit_field +0000000120082f80 t store_constructor +00000001200733f0 T store_expr +0000000120074000 t store_field +000000012008ab00 t store_fixed_bit_field +0000000120025700 T store_init_value +00000001200891e0 t store_one_arg +00000001200152a0 T store_parm_decls +000000012008afe0 t store_split_bit_field +0000000120101e80 t strength_reduce +000000012013c930 T strict_memory_address_p +0000000120084b90 t string_constant +00000001201ffe78 S string_ftype_ptr_ptr +00000001200d8790 t string_length_attribute +00000001201ffc28 S string_type_node +00000001201cf0c0 r strings_107.2 +00000001201cf110 r strings_108.3 +00000001201cf138 r strings_114.4 +00000001201cf158 r strings_117.5 +00000001201cf178 r strings_120.6 +00000001201cf188 r strings_121.7 +00000001201cf1c8 r strings_126.8 +00000001201cf1d8 r strings_127.9 +00000001201cf218 r strings_131.10 +00000001201cf228 r strings_132.11 +00000001201cf268 r strings_147.12 +00000001201cf280 r strings_149.13 +00000001201cf298 r strings_151.14 +00000001201cf2b0 r strings_154.15 +00000001201cf2d0 r strings_156.16 +00000001201cf2f0 r strings_158.17 +00000001201cf310 r strings_169.18 +00000001201cf320 r strings_228.19 +00000001201cf340 r strings_233.20 +00000001201cf358 r strings_245.21 +00000001201cf368 r strings_247.22 +00000001201cf378 r strings_249.23 +00000001201cf388 r strings_252.24 +00000001201cf398 r strings_261.25 +00000001201cf3a8 r strings_262.26 +00000001201cf3b8 r strings_264.27 +00000001201cf3c8 r strings_281.28 +00000001201cf080 r strings_58.0 +00000001201cf0a0 r strings_61.1 +0000000120058b80 t strip_compound_expr +0000000120038e50 T strip_off_ending +00000001202006a8 S strlen_optab +00000001202007a8 S struct_value_incoming_rtx +0000000120200790 S struct_value_rtx +0000000120113120 t stupid_find_reg +00000001201128c0 T stupid_life_analysis +0000000120113470 t stupid_mark_refs +0000000120113aa0 t stupid_reg_compare +0000000120200478 S sub_optab +00000001201ff238 s subflg +000000012020ba00 B sublevel_ixpansions +00000001200b4110 T subreg_lowpart_p +00000001200b3fc0 T subreg_realpart_p +00000001200d7a80 t subscript_data_attribute +00000001201188c0 t subst +00000001200de850 t subst_constants +0000000120142000 t subst_indexed_address +00000001201ff5d8 s subst_insn +00000001201ff5e8 s subst_low_cuid +00000001201ff5e0 s subst_prev_insn +0000000120141ec0 t subst_reg_equivs +00000001201ff868 s subst_reg_equivs_changed +0000000120143600 T subst_reloads +000000012003e4d0 T substitute_in_expr +000000012003e800 T substitute_in_type +00000001200425a0 T suspend_momentary +00000001200e69c0 T swap_condition +000000012019b560 T sym_lookup +0000000120197460 T symbolic_address_p +0000000120198ae0 T symbolic_operand +00000001201fff18 S symout_time +000000012008d240 t synth_mult +00000001201ff008 s table +0000000120206510 b table +00000001201e8fe0 d table.0 +0000000120067350 t tail_recursion_args +0000000120200200 S tail_recursion_label +0000000120200228 S tail_recursion_reentry +00000001202006e8 S target_flags +00000001201ff960 s target_hash_table +0000000120056170 T target_isinf +00000001200561d0 T target_isnan +0000000120056260 T target_negative +00000001201e8558 D target_options +00000001201e8388 D target_switches +00000001202002e8 S target_temp_slot_level +00000001200a8300 T tdesc_section +0000000120200128 S temp_decl_firstobj +00000001202011a8 b temp_decl_obstack +00000001202066a8 b temp_obstack +0000000120200174 S temp_slot_level +0000000120200180 S temp_slots +00000001200438b0 T temp_tree_cons +0000000120042110 T temporary_allocation +0000000120200120 S temporary_firstobj +000000012020be48 B temporary_obstack +00000001200e3e20 t tension_vector_labels +00000001200a84f0 T text_section +00000001201e79e8 d tfaff +00000001201ff604 s this_basic_block +00000001201ff078 s this_function_bytecode +00000001201ff080 s this_function_calldesc +00000001201ff070 s this_function_callinfo +00000001201ff068 s this_function_decl +00000001201ff3a8 s this_insn +00000001201ff768 s this_insn +00000001201ff850 s this_insn +00000001201ff858 s this_insn_is_asm +00000001201ff764 s this_insn_number +00000001201ffb00 s this_is_asm_operands +00000001200e58c0 T thread_jumps +00000001200613a0 T thread_prologue_and_epilogue_insns +00000001201eb3a5 d tm_rcs_id +00000001200be4f0 t toe113 +00000001200be8d0 t toe24 +00000001200b93d0 t toe53 +00000001200be680 t toe64 +00000001201ffbf8 S token_buffer +00000001202000b0 S toplev_inline_obstacks +00000001201ff5a0 s total_attempts +00000001201ff5a8 s total_extras +00000001201ff5a4 s total_merges +00000001201ff5ac s total_successes +0000000120200a20 S trampoline +000000012005ef80 T trampoline_address +00000001201ff038 s trampoline_list +0000000120145820 T transfer_replacements +0000000120200098 S tree_code_length +0000000120200100 S tree_code_name +00000001202000d8 S tree_code_type +000000012003e370 T tree_cons +0000000120040ed0 T tree_int_cst_equal +0000000120044ac0 T tree_int_cst_lt +0000000120044b70 T tree_int_cst_sgn +0000000120043670 T tree_last +000000012020bd58 B tree_node_counts +00000001201e8f50 D tree_node_kind_names +000000012020bea0 B tree_node_sizes +0000000120164460 T true_dependence +00000001200e7190 T true_regnum +0000000120200570 S truncdfsf2_libfunc +0000000120200450 S trunctfdf2_libfunc +0000000120200628 S trunctfsf2_libfunc +0000000120200640 S truncxfdf2_libfunc +0000000120200390 S truncxfsf2_libfunc +000000012002c1a0 T truthvalue_conversion +0000000120114730 t try_combine +00000001200de6e0 T try_constants +000000012015d8b0 t try_merge_delay_insns +00000001200b2940 T try_split +0000000120200300 S tst_optab +000000012004bce0 t twoval_comparison_p +00000001201fed34 s type.1 +00000001200c9400 t type_attribute +000000012002b270 T type_for_mode +000000012002d3e0 T type_for_size +0000000120044950 T type_hash_add +0000000120040880 T type_hash_canon +0000000120044780 T type_hash_list +00000001200447b0 T type_hash_lookup +000000012020bb80 B type_hash_table +00000001200cede0 t type_is_fundamental +0000000120044a00 T type_list_equal +0000000120019ab0 t type_lists_compatible_p +0000000120045220 T type_precision +00000001201ebdf8 D typecode_mode +0000000120200398 S ucmp_optab +0000000120200508 S udiv_optab +0000000120200620 S udivmod_optab +00000001201ff500 s uid_block_number +00000001201ff400 s uid_cuid +00000001201ff5b0 s uid_cuid +0000000120200850 S uid_loop_num +0000000120200860 S uid_luid +00000001201ff550 s uid_suid +00000001201ff970 s uid_to_ruid +00000001201ff508 s uid_volatile +0000000120200588 S umax_optab +0000000120200590 S umin_optab +00000001202005b8 S umod_optab +0000000120200578 S umul_highpart_optab +00000001202003c0 S umul_widen_optab +000000012001f100 t unary_complex_lvalue +00000001201fed18 s undeclared_variable_notice +0000000120117840 t undo_all +0000000120206700 b undobuf +00000001201ff950 s unfilled_firstobj +00000001202094b0 b unfilled_slots_obstack +0000000120062fe0 T uninitialized_vars_warning +0000000120209770 b unit_last_insn +00000001202097dc b unit_n_insns +00000001202097b8 b unit_tick +00000001201ff49c s unknown_address_altered +00000001201ff248 s unnamed_struct_number +000000012006f630 T unroll_block_trees +0000000120107ce0 T unroll_loop +00000001200b4660 T unshare_all_rtl +00000001201ffce0 S unsigned_char_type_node +00000001200e6a90 T unsigned_condition +000000012002cea0 T unsigned_conversion_warning +00000001201ffd00 S unsigned_intDI_type_node +00000001201ffe48 S unsigned_intHI_type_node +00000001201ffe68 S unsigned_intQI_type_node +00000001201ffcf0 S unsigned_intSI_type_node +000000012020ae18 b unsigned_mode_to_code_map +0000000120024fd0 T unsigned_type +00000001201ffd20 S unsigned_type_node +00000001201ffc70 S unsigned_wchar_type_node +00000001201ffa88 s unused_expr_list +00000001201ffa80 s unused_insn_list +0000000120158050 t update_block +00000001201317d0 t update_equiv_regs +0000000120167ad0 t update_flow_info +00000001201043c0 t update_giv_derive +0000000120159d50 t update_live_status +0000000120133de0 t update_qty_class +0000000120106f50 t update_reg_last_use +000000012012ce30 t update_table_tick +0000000120061cd0 T update_temp_slot_address +00000001201ff0d8 s use_cost_table +0000000120129d70 t use_crosses_set_p +00000001201fef40 S use_gnu_debug_info_extensions +00000001200824b0 T use_reg +0000000120082550 T use_regs +00000001200fc0a0 t use_related_value +0000000120062b70 T use_variable +0000000120062c40 T use_variable_after +000000012010eb40 t uses_reg_or_mem +0000000120039230 t v_message_with_decl +0000000120025ed0 t valid_compound_expr_initializer +0000000120103530 t valid_initial_value_p +00000001200442c0 T valid_machine_attribute +0000000120172eb0 T validate_change +00000001201351a0 t validate_equiv_mem_from_store +0000000120173020 T validate_replace_rtx +0000000120170180 t validate_replace_rtx_1 +0000000120095730 T validize_mem +00000001201fed40 s value.3 +00000001200434b0 T value_member +00000001202006e4 S var_labelno +00000001201ff090 s var_offset +00000001201fffd0 S varconst_time +00000001201ffb90 s variable_args_p +0000000120048ef0 T variable_size +00000001201fec30 G version_string +0000000120200740 S virtual_incoming_args_rtx +0000000120200758 S virtual_outgoing_args_rtx +00000001202007b0 S virtual_stack_dynamic_rtx +0000000120200720 S virtual_stack_vars_rtx +00000001201ff060 s virtuals_instantiated +00000001201ffd40 S void_ftype_ptr_int_int +00000001201ffc50 S void_ftype_ptr_ptr_int +00000001201ffd90 S void_type_node +00000001200aead0 T volatile_insn_p +00000001202009cc S volatile_ok +00000001200aec60 T volatile_refs_p +000000012016e310 t walk_alter_subreg +000000012005bec0 t walk_fixup_memory_subreg +00000001201fedc4 s warn_about_return_type +0000000120200044 S warn_aggregate_return +00000001201ffe24 S warn_bad_function_cast +0000000120200080 S warn_cast_align +00000001201ffd60 S warn_cast_qual +00000001201fed64 S warn_char_subscripts +00000001201ffd10 S warn_conversion +0000000120021280 t warn_for_assignment +00000001201ffe10 S warn_format +00000001201fffe8 S warn_id_clash +00000001200652c0 T warn_if_unused_value +00000001201ffc10 S warn_implicit +00000001201ffed4 S warn_inline +00000001201fff74 S warn_larger_than +00000001201ffc90 S warn_missing_braces +00000001201ffdec S warn_missing_declarations +00000001201ffde8 S warn_missing_prototypes +00000001201fed60 S warn_nested_externs +00000001201ffdfc S warn_parentheses +00000001201ffe30 S warn_pointer_arith +00000001201fed5c S warn_redundant_decls +0000000120200020 S warn_return_type +00000001201fff40 S warn_shadow +00000001201ffc84 S warn_strict_prototypes +00000001201fff70 S warn_switch +00000001201ffda8 S warn_traditional +00000001201fff64 S warn_uninitialized +00000001201ffee4 S warn_unused +00000001201ffc80 S warn_write_strings +0000000120031500 T warning +00000001200310d0 T warning_for_asm +0000000120025f70 t warning_init +00000001201fefd8 s warning_message.0 +0000000120030e20 T warning_with_decl +0000000120030ae0 T warning_with_file_and_line +00000001201fef48 S warningcount +00000001201fefc8 S warnings_are_errors +00000001201ffc20 S wchar_array_type_node +00000001201ffd28 S wchar_type_node +00000001201ff158 s weak_decls +00000001200a9be0 T weak_finish +00000001202009d4 S which_alternative +00000001201341f0 t wipe_dead_reg +00000001202007a0 S word_mode +00000001201e6a58 d wordlist +00000001200c8b80 t write_modifier_bytes +00000001201fef38 S write_symbols +0000000120205f80 b wstring +0000000120038bd0 T xmalloc +00000001202004d8 S xor_optab +0000000120038c30 T xrealloc +00000001200171f0 T xref_tag +00000001201ffbe8 S yychar +00000001201a35c0 r yycheck +00000001201ffbdc S yydebug +00000001201a18ac r yydefact +00000001201a1dd2 r yydefgoto +000000012000ba50 T yyerror +0000000120008e00 T yylex +00000001201ffbe0 S yylval +00000001201ffbd8 S yynerrs +00000001201a1ef2 r yypact +0000000120001ad0 T yyparse +00000001201a2418 r yypgoto +000000012019fc46 r yyprhs +000000012000b900 T yyprint +00000001201a12d0 r yyr1 +00000001201a15be r yyr2 +000000012019ff34 r yyrhs +00000001201a08b8 r yyrline +00000001201a2538 r yytable +00000001201a0ba8 r yytname +000000012019fb08 r yytranslate +00000001201ffbb8 s zero.2 +00000001201ff140 s zero_cost diff --git a/simulators/gem5/configs/boot/devtime.rcS b/simulators/gem5/configs/boot/devtime.rcS new file mode 100644 index 00000000..4d1ca940 --- /dev/null +++ b/simulators/gem5/configs/boot/devtime.rcS @@ -0,0 +1,8 @@ +insmod /modules/devtime.ko dataAddr=0x9000008 count=100 +rmmod devtime +insmod /modules/devtime.ko dataAddr=0x1a0000300 count=100 +rmmod devtime +insmod /modules/devtime.ko memTest=1 count=100 +rmmod devtime +m5 exit + diff --git a/simulators/gem5/configs/boot/equake.rcS b/simulators/gem5/configs/boot/equake.rcS new file mode 100644 index 00000000..6b799aaf --- /dev/null +++ b/simulators/gem5/configs/boot/equake.rcS @@ -0,0 +1,12 @@ +#!/bin/sh + +cd /benchmarks/spec/equake00/ + +/sbin/m5 checkpoint 0 0 +/sbin/m5 checkpoint 100000000 200000000 + +/sbin/m5 loadsymbol + +/sbin/m5 resetstats +/benchmarks/spec/equake00/equake < lgred.in +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/equake.symbol b/simulators/gem5/configs/boot/equake.symbol new file mode 100644 index 00000000..4b28299c --- /dev/null +++ b/simulators/gem5/configs/boot/equake.symbol @@ -0,0 +1,94 @@ +000000012001a868 S ARCHcholeskylen +000000012001a878 S ARCHcoord +000000012001a930 S ARCHcorners +000000012001a938 S ARCHduration +000000012001a940 S ARCHelems +000000012001a8b0 S ARCHglobalelem +000000012001a8d0 S ARCHglobalelems +000000012001a8e8 S ARCHglobalnode +000000012001a8a8 S ARCHglobalnodes +000000012001a8d8 S ARCHmatrixcol +000000012001a898 S ARCHmatrixindex +000000012001a924 S ARCHmatrixlen +000000012001a8ac S ARCHmesh_dim +000000012001a8f8 S ARCHmine +000000012001a90c S ARCHnodes +000000012001a908 S ARCHpriv +000000012001a920 S ARCHsubdomains +000000012001a8b8 S ARCHvertex +000000012001a900 S C +000000012001a918 S C23 +000000012001a9a8 B Damp +000000012001a9c8 B Exc +000000012001a8a0 S K +000000012001a928 S M +000000012001a888 S M23 +000000012001a950 B Src +000000012001a890 S V23 +000000012001a388 D _DYNAMIC +000000012001a5f8 D _GLOBAL_OFFSET_TABLE_ +000000012001a848 G _IO_stdin_used +000000012001a550 T _PROCEDURE_LINKAGE_TABLE_ +000000012001a530 d __CTOR_END__ +000000012001a528 d __CTOR_LIST__ +000000012001a540 d __DTOR_END__ +000000012001a538 d __DTOR_LIST__ +000000012001a384 r __FRAME_END__ +000000012001a548 d __JCR_END__ +000000012001a548 d __JCR_LIST__ +000000012001a860 A __bss_start +000000012001a000 D __data_start +0000000120008c50 t __do_global_ctors_aux +00000001200008d0 t __do_global_dtors_aux +000000012001a850 G __dso_handle +000000012001a000 A __fini_array_end +000000012001a000 A __fini_array_start +000000012001a000 A __init_array_end +000000012001a000 A __init_array_start +0000000120008bb0 T __libc_csu_fini +0000000120008b00 T __libc_csu_init +0000000120000890 W __start +000000012001a860 A _edata +000000012001a9e0 A _end +0000000120008cb0 T _fini +0000000120000828 T _init +0000000120000890 T _start +00000001200049c4 T abe_matrix +00000001200056b8 T arch_bail +00000001200056e4 T arch_info +0000000120006584 T arch_init +00000001200057e0 T arch_parsecommandline +0000000120005bf4 T arch_readdouble +0000000120005ad0 T arch_readelemvector +00000001200059ac T arch_readnodevector +0000000120004530 T area_triangle +00000001200051e8 T centroid +000000012001a860 s completed.1 +000000012001a000 W data_start +000000012001a948 S disp +00000001200050bc T distance +0000000120003c70 T element_matrices +0000000120000970 t frame_dummy +00000001200036f8 T get_Enu +0000000120003820 T inv_J +00000001200009c0 T main +0000000120007a88 T mem_init +00000001200054b8 T mv12x12 +000000012001a8c0 S nodekind +000000012001a910 S nodekindf +000000012001a8f0 S options +000000012001a858 g p.0 +000000012001a8c8 S packfile +0000000120004bc4 T phi0 +0000000120004cc4 T phi1 +0000000120004d98 T phi2 +00000001200052e8 T point2fault +000000012001a870 S progname +0000000120005cd8 T readpackfile +000000012000360c T shape_ders +0000000120004e84 T slip +0000000120006604 T smvp +00000001200070f8 T smvp_opt +000000012001a880 S source_elms +000000012001a8e0 S vel +000000012000561c T vv12x12 diff --git a/simulators/gem5/configs/boot/gcc.rcS b/simulators/gem5/configs/boot/gcc.rcS new file mode 100644 index 00000000..6bcd7e03 --- /dev/null +++ b/simulators/gem5/configs/boot/gcc.rcS @@ -0,0 +1,12 @@ +#!/bin/sh + +cd /benchmarks/spec/gcc00/ + +/sbin/m5 checkpoint 0 0 +/sbin/m5 checkpoint 100000000 200000000 + +/sbin/m5 loadsymbol + +/sbin/m5 resetstats +./cc1 mdred.rtlanal.i +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/gzip.rcS b/simulators/gem5/configs/boot/gzip.rcS new file mode 100644 index 00000000..c7aca7e9 --- /dev/null +++ b/simulators/gem5/configs/boot/gzip.rcS @@ -0,0 +1,12 @@ +#!/bin/sh + +cd /benchmarks/spec/gzip00/ + +/sbin/m5 checkpoint 0 0 +/sbin/m5 checkpoint 100000000 200000000 + +/sbin/m5 loadsymbol + +/sbin/m5 resetstats +./gzip lgred.log 1 +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/gzip.symbol b/simulators/gem5/configs/boot/gzip.symbol new file mode 100644 index 00000000..d965c99a --- /dev/null +++ b/simulators/gem5/configs/boot/gzip.symbol @@ -0,0 +1,268 @@ +0000000120022c08 D _DYNAMIC +0000000120022fd0 D _GLOBAL_OFFSET_TABLE_ +0000000120023498 G _IO_stdin_used +0000000120022dc0 T _PROCEDURE_LINKAGE_TABLE_ +0000000120022da0 d __CTOR_END__ +0000000120022d98 d __CTOR_LIST__ +0000000120022db0 d __DTOR_END__ +0000000120022da8 d __DTOR_LIST__ +0000000120022c04 r __FRAME_END__ +0000000120022db8 d __JCR_END__ +0000000120022db8 d __JCR_LIST__ +00000001200234f8 A __bss_start +0000000120021030 D __data_start +000000012000fbc0 t __do_global_ctors_aux +00000001200012a0 t __do_global_dtors_aux +00000001200234a0 G __dso_handle +0000000120021030 A __fini_array_end +0000000120021030 A __fini_array_start +0000000120021030 A __init_array_end +0000000120021030 A __init_array_start +000000012000fb20 T __libc_csu_fini +000000012000fa70 T __libc_csu_init +0000000120001260 W __start +00000001200234f8 A _edata +0000000120073b10 A _end +000000012000fc20 T _fini +00000001200011f8 T _init +0000000120001260 T _start +0000000120004cf0 T abort_gzip +000000012000de80 T add_envopt +0000000120023550 S args +0000000120023520 S ascii +000000012002551c b base_dist +00000001200254a8 b base_length +0000000120023698 S bb +00000001200234fc s bi_buf +0000000120001ad0 T bi_init +0000000120001b20 T bi_reverse +0000000120023500 s bi_valid +00000001200015d0 T bi_windup +00000001200235b8 s bitbuf +00000001200235e0 s bitbuf +00000001200235c0 s bitcount +0000000120023690 S bk +0000000120024654 b bl_count +0000000120021830 d bl_desc +0000000120021858 d bl_order +00000001200245b8 b bl_tree +00000001200234ec G block_mode +0000000120023610 S block_start +00000001200235b4 s blocksize +0000000120021540 d border +0000000120009620 t build_tree +0000000120023650 S bytes_in +0000000120023668 S bytes_out +0000000120004740 t check_ofname +000000012000d5c0 T check_zipfile +000000012000e540 T clear_bufs +00000001200234f8 s completed.1 +0000000120023518 s compr_level +00000001200092e0 t compress_block +00000001200235a0 s compressed_len +0000000120021030 d configuration_table +000000012000e280 T copy +00000001200017d0 T copy_block +0000000120004ae0 t copy_stat +0000000120021644 d cpdext +0000000120021608 d cpdist +000000012002158c d cplens +00000001200215ca d cplext +00000001200235f8 s crc +00000001200234f0 g crc.0 +0000000120021870 D crc_32_tab +0000000120002b90 t create_outfile +0000000120008450 T ct_init +0000000120008f60 T ct_tally +000000012002ea20 B d_buf +0000000120021808 d d_desc +0000000120021030 W data_start +00000001200234e8 G dbglvl +00000001200234e4 G dbits +0000000120008440 T debug_time +000000012000a5e0 t decode +000000012000ad50 t decode_c +000000012000ab90 t decode_start +0000000120023528 S decompress +00000001200236c0 S decrypt +0000000120002250 T deflate +0000000120002770 t deflate_fast +0000000120024f68 b depth +000000012000ee70 T display_ratio +00000001200252a5 b dist_code +0000000120004c60 t do_exit +0000000120003f00 t do_list +0000000120023540 S do_lzw +00000001200235c8 s done +0000000120023fcc b dyn_dtree +00000001200236d8 b dyn_ltree +0000000120023678 S env +000000012002350c s eofile +000000012000e1c0 T error +0000000120023548 S exit_code +00000001200235f4 S ext_header +0000000120021794 d extra_blbits +000000012002171c d extra_dbits +00000001200216a8 d extra_lbits +00000001200236b8 S file_method +000000012000f9c0 T file_read +00000001200236b0 S file_type +000000012000e580 T fill_inbuf +0000000120002030 t fill_window +00000001200234d8 g first_time.2 +000000012002358d s flag_bit +0000000120025594 b flag_buf +000000012002358c s flags +0000000120008ba0 T flush_block +000000012000e730 T flush_outbuf +000000012000e860 T flush_window +000000012002352c S force +0000000120023640 S foreground +0000000120001340 t frame_dummy +000000012000a1a0 t gen_bitlen +0000000120008a80 t gen_codes +0000000120002dd0 t get_istat +00000001200032c0 T get_method +0000000120004d50 t get_suffix +0000000120023618 S good_match +000000012000ebf0 T gzipbasename +00000001200236d0 S header_bytes +0000000120024674 b heap +0000000120023578 s heap_len +000000012002357c s heap_max +00000001200214b8 d help_msg.5 +0000000120004ee0 T huft_build +0000000120005670 T huft_free +00000001200236a0 S hufts +00000001200235b0 s i.0 +0000000120023688 S ifd +0000000120023658 S ifile_size +000000012005eea8 B ifname +000000012002356c s in_exit.4 +00000001200269e0 B inbuf +0000000120006e00 T inflate +0000000120006bf0 T inflate_block +00000001200056d0 T inflate_codes +00000001200062b0 T inflate_dynamic +00000001200060f0 T inflate_fixed +0000000120005e10 T inflate_stored +0000000120008960 t init_block +0000000120023684 S inptr +00000001200235a8 s input_len +0000000120023508 s ins_h +0000000120023644 S insize +000000012003ea20 B istat +00000001200235c4 s j +00000001200236c8 S key +00000001200213f8 d known_suffixes.0 +00000001200217e0 d l_desc +0000000120023584 s last_dist +0000000120023588 s last_flags +0000000120023580 s last_lit +000000012002364c S last_member +00000001200234e0 G lbits +0000000120026910 b leaves +00000001200251a5 b length_code +00000001200234c8 G level +0000000120021080 d license_msg +0000000120023534 S list +00000001200268a8 b lit_base +00000001200267a8 b literal +0000000120001b60 T lm_init +0000000120001d90 T longest_match +00000001200210f8 D longopts +0000000120023510 s lookahead +0000000120006ed0 T lzw +0000000120007a80 T main +0000000120003040 t make_ofname +000000012000ec40 T make_simple_name +000000012000c130 t make_table +0000000120021680 D mask_bits +0000000120023624 S match_start +000000012002361c S max_chain_length +0000000120023514 s max_lazy_match +00000001200235d8 s max_len +00000001200234c0 G maxbits +00000001200234c4 G method +0000000120021470 d methods.3 +0000000120023570 s msg_done +0000000120004310 t name_too_long +0000000120023608 S nice_match +00000001200234b8 G no_name +00000001200234bc G no_time +0000000120023630 S ofd +000000012003eaa8 B ofname +0000000120023590 s opt_len +00000001200235d0 s orig_len +000000012005f2a8 B outbuf +0000000120023648 S outcnt +00000001200234a8 g p.0 +0000000120026978 b parents +0000000120023680 S part_nb +00000001200235dc s peek_bits +00000001200235f0 S pkzip +000000012003eea8 B prev +000000012002360c S prev_length +0000000120023628 S progname +0000000120026594 b pt_len +00000001200265a8 b pt_table +000000012002353c S quiet +00000001200080c0 T ran +0000000120023600 S read_buf +000000012000b8c0 t read_c_len +000000012000ed50 T read_error +000000012000b130 t read_pt_len +000000012000d2a0 t read_tree +0000000120023530 S recursive +0000000120023568 S remove_ofname +0000000120023660 S save_orig_name +0000000120009d90 t scan_tree +00000001200236a8 S seedi +0000000120001390 T send_bits +0000000120009f40 t send_tree +0000000120009540 t set_file_type +0000000120004420 t shorten_name +0000000120007f90 T spec_compress +0000000120073ac8 B spec_fd +0000000120007800 T spec_getc +0000000120006f70 T spec_init +0000000120007f40 T spec_initbufs +0000000120007430 T spec_load +0000000120008350 T spec_putc +0000000120007090 T spec_random_load +0000000120007670 T spec_read +00000001200081b0 T spec_reset +0000000120008190 T spec_rewind +0000000120008010 T spec_uncompress +0000000120007930 T spec_ungetc +0000000120008210 T spec_write +0000000120024540 b static_dtree +0000000120023598 s static_len +00000001200240c0 b static_ltree +000000012000eb20 T strlwr +0000000120023620 S strstart +00000001200235bc s subbitbuf +0000000120021440 d suffixes.1 +0000000120023544 S test +0000000120023638 S time_stamp +0000000120023524 S to_stdout +0000000120023558 S total_in +0000000120023560 S total_out +000000012000a510 T unlzh +000000012000c5c0 T unlzw +000000012000cde0 T unpack +000000012000d7a0 T unzip +000000012000e4c0 T updcrc +00000001200235e8 s valid +0000000120023538 S verbose +000000012000ecd0 T warn +0000000120063aa8 B window +00000001200234b0 G window_size +00000001200234d0 G work +000000012000ea20 T write_buf +000000012000ee00 T write_error +000000012000e220 T xmalloc +0000000120023670 S z_len +0000000120073aa8 B z_suffix +0000000120023504 s zfile +000000012000ef80 T zip diff --git a/simulators/gem5/configs/boot/hack_back_ckpt.rcS b/simulators/gem5/configs/boot/hack_back_ckpt.rcS new file mode 100644 index 00000000..4c38a4d3 --- /dev/null +++ b/simulators/gem5/configs/boot/hack_back_ckpt.rcS @@ -0,0 +1,62 @@ +#!/bin/sh + +# +# This is a tricky script to understand. When run in M5, it creates +# a checkpoint after Linux boot up, but before any benchmarks have +# been run. By playing around with environment variables, we can +# detect whether the checkpoint has been taken. +# - If the checkpoint hasn't been taken, the script allows M5 to checkpoint the system, +# re-read this script into a new tmp file, and re-run it. On the +# second execution of this script (checkpoint has been taken), the +# environment variable is already set, so the script will exit the +# simulation +# - When we restore the simulation from a checkpoint, we can +# specify a new script for M5 to execute in the full-system simulation, +# and it will be executed as if a checkpoint had just been taken. +# +# Author: +# Joel Hestness, hestness@cs.utexas.edu +# while at AMD Research and Advanced Development Lab +# Date: +# 10/5/2010 +# + +# Test if the RUNSCRIPT_VAR environment variable is already set +if [ "${RUNSCRIPT_VAR+set}" != set ] +then + # Signal our future self that it's safe to continue + export RUNSCRIPT_VAR=1 +else + # We've already executed once, so we should exit + /sbin/m5 exit +fi + +# Checkpoint the first execution +echo "Checkpointing simulation..." +/sbin/m5 checkpoint + +# Test if we previously okayed ourselves to run this script +if [ "$RUNSCRIPT_VAR" -eq 1 ] +then + + # Signal our future self not to recurse infinitely + export RUNSCRIPT_VAR=2 + + # Read the script for the checkpoint restored execution + echo "Loading new script..." + /sbin/m5 readfile > /tmp/runscript + chmod 755 /tmp/runscript + + # Execute the new runscript + if [ -s /tmp/runscript ] + then + exec /tmp/runscript + else + echo "Script not specified. Dropping into shell..." + /bin/bash + fi + +fi + +echo "Fell through script. Exiting..." +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/halt.sh b/simulators/gem5/configs/boot/halt.sh new file mode 100644 index 00000000..b1332eba --- /dev/null +++ b/simulators/gem5/configs/boot/halt.sh @@ -0,0 +1 @@ +m5 exit diff --git a/simulators/gem5/configs/boot/iscsi-client.rcS b/simulators/gem5/configs/boot/iscsi-client.rcS new file mode 100644 index 00000000..cfa87652 --- /dev/null +++ b/simulators/gem5/configs/boot/iscsi-client.rcS @@ -0,0 +1,107 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig lo 127.0.0.1 +/sbin/ifconfig eth0 192.168.0.10 txqueuelen 1000 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +#echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "1" > /proc/sys/vm/dirty_writeback_centisecs +echo "done." + +cat > /etc/initiatorname.iscsi < /etc/iscsid.conf < /var/log/iscsi.log +chmod 0600 /var/log/iscsi.log +chmod 0666 -R /var/db/iscsi + +# Required for udev to activate/deactivate devices. +echo "/sbin/hotplug" > /proc/sys/kernel/hotplug + +/sbin/insmod /modules/scsi_transport_iscsi.ko +/sbin/insmod /modules/iscsi_tcp.ko + +echo "Starting iscsid..." +/iscsi/iscsid -f & + +sleep 1 + +echo "Waiting for server..." +netcat -c -l -p 8000 + +echo "Attaching target..." +/iscsi/iscsiadm -m discovery -t st -p 192.168.0.1 +/iscsi/iscsiadm -m node -r a0c049 --login +echo "done." + +sleep 5 + +#PARAMS="-n 8 -s 8 -r .666 -c 50" # lisa default +#PARAMS="-n 8 -s 5120 -r .666 -c 20" # very unstable +#PARAMS="-n 8 -s 8 -r 0 -c 20" # very unstable +#PARAMS="-n 8 -s 8 -r 1 -c 20" # stable 960 Mbps +#PARAMS="-n 8 -s 1024 -r 1 -c 20" # very unstable +#PARAMS="-n 16 -s 32 -r 1 -c 50" # stable ~1.5 Gbps +#PARAMS="-n 50 -s 32 -r 1 -c 50" # stable ~1.5 Gbps +PARAMS="-n 50 -s 8 -r .666 -c 50" +COMMAND="/benchmarks/aio-bench $PARAMS -i 1000000 -C 50000 /dev/sda" + +echo "Starting aio benchmark..." +echo $COMMAND +eval $COMMAND + +echo "starting bash shell..." +/bin/bash + +echo -n "halting machine" +m5 exit diff --git a/simulators/gem5/configs/boot/iscsi-server.rcS b/simulators/gem5/configs/boot/iscsi-server.rcS new file mode 100644 index 00000000..210f4eae --- /dev/null +++ b/simulators/gem5/configs/boot/iscsi-server.rcS @@ -0,0 +1,59 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig lo 127.0.0.1 +/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "10" > /proc/sys/vm/dirty_writeback_centisecs +echo "done." + +# specific for iscsi-target +MEM_SIZE=1048576 +echo ${MEM_SIZE} > /proc/sys/net/core/wmem_max +echo ${MEM_SIZE} > /proc/sys/net/core/rmem_max +echo ${MEM_SIZE} > /proc/sys/net/core/wmem_default +echo ${MEM_SIZE} > /proc/sys/net/core/rmem_default +echo "${MEM_SIZE} ${MEM_SIZE} ${MEM_SIZE}" > /proc/sys/net/ipv4/tcp_mem +echo "${MEM_SIZE} ${MEM_SIZE} ${MEM_SIZE}" > /proc/sys/net/ipv4/tcp_rmem +echo "${MEM_SIZE} ${MEM_SIZE} ${MEM_SIZE}" > /proc/sys/net/ipv4/tcp_wmem + +mke2fs -F /dev/sda + +cat > /etc/ietd.conf < /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for natbox..." +netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="TCP_MAERTS" +SHORT_ARGS="-l -100k" +LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 200000000 2000000000 +/sbin/m5 checkpoint 200000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nat-netperf-server.rcS b/simulators/gem5/configs/boot/nat-netperf-server.rcS new file mode 100644 index 00000000..23b99a13 --- /dev/null +++ b/simulators/gem5/configs/boot/nat-netperf-server.rcS @@ -0,0 +1,32 @@ +#!/bin/sh +SERVER=192.168.0.1 +CLIENT=10.0.0.2 +NATBOX=192.168.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $SERVER txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo "running netserver..." +/benchmarks/netperf-bin/netserver + +echo -n "signal natbox to begin..." +sleep 5 +echo "server ready" | netcat -c $NATBOX 8000 +echo "done." + +echo "starting bash..." +exec /bin/bash diff --git a/simulators/gem5/configs/boot/nat-netperf-stream-client.rcS b/simulators/gem5/configs/boot/nat-netperf-stream-client.rcS new file mode 100644 index 00000000..f20e92c5 --- /dev/null +++ b/simulators/gem5/configs/boot/nat-netperf-stream-client.rcS @@ -0,0 +1,50 @@ +#!/bin/sh +SERVER=192.168.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo "modifying route table" +route add default gw 10.0.0.1 + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="TCP_STREAM" +SHORT_ARGS="-l -100k" +LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 ivlb 1 +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 200000000 2000000000 +/sbin/m5 checkpoint 200000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nat-spec-surge-client.rcS b/simulators/gem5/configs/boot/nat-spec-surge-client.rcS new file mode 100644 index 00000000..d26e3837 --- /dev/null +++ b/simulators/gem5/configs/boot/nat-spec-surge-client.rcS @@ -0,0 +1,51 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# +CLIENT=10.0.0.2 +SERVER=192.168.0.1 + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 $CLIENT txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo "changing route table..." +route add default gw 10.0.0.1 + +echo "waiting for server..." +netcat -c -l -p 8000 + +echo -n "running surge client..." +/bin/bash -c "cd /benchmarks/surge && ./spec-m5 1 20 1 $SERVER 5 40000 1000000000 1000" +echo "done." + +echo -n "halting machine" +m5 exit + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/nat-spec-surge-server.rcS b/simulators/gem5/configs/boot/nat-spec-surge-server.rcS new file mode 100755 index 00000000..0f462568 --- /dev/null +++ b/simulators/gem5/configs/boot/nat-spec-surge-server.rcS @@ -0,0 +1,56 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# +NATBOX=192.168.0.7 + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000 +/sbin/ifconfig eth0:1 192.168.0.2 txqueuelen 1000 +/sbin/ifconfig eth0:2 192.168.0.3 txqueuelen 1000 +/sbin/ifconfig eth0:3 192.168.0.4 txqueuelen 1000 +/sbin/ifconfig eth0:4 192.168.0.5 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "mounting file set..." +mkdir -p /z/htdocs +mount /dev/hdb1 /z/htdocs +echo "done." + +echo -n "starting httpd..." +/benchmarks/apache2/bin/apachectl start +sleep 2 +cat /benchmarks/apache2/logs/error_log +echo "done." + +echo "notifying natbox..." +sleep 5 +echo "server ready" | netcat -c $NATBOX 8000 +echo "done" + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/natbox-netperf.rcS b/simulators/gem5/configs/boot/natbox-netperf.rcS new file mode 100644 index 00000000..e6384757 --- /dev/null +++ b/simulators/gem5/configs/boot/natbox-netperf.rcS @@ -0,0 +1,53 @@ +#!/bin/sh +EXTIF=192.168.0.2 +INTIF=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $EXTIF txqueuelen 1000 +ifconfig eth1 $INTIF txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog +echo "1" > /proc/sys/net/ipv4/ip_forward + +echo "waiting for netserver..." +netcat -c -l -p 8000 + +echo "setting up iptables..." +IPTABLES=/sbin/iptables +EXTIF=eth0 +INTIF=eth1 + +$IPTABLES -P INPUT ACCEPT +$IPTABLES -F INPUT +$IPTABLES -P OUTPUT ACCEPT +$IPTABLES -F OUTPUT +$IPTABLES -P FORWARD DROP +$IPTABLES -F FORWARD +$IPTABLES -t nat -F + +$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT +$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT +$IPTABLES -A FORWARD -j LOG + +$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE + +echo "informing client..." +sleep 5 +echo "server ready" | netcat -c $CLIENT 8000 + +echo "starting bash..." +exec /bin/bash diff --git a/simulators/gem5/configs/boot/natbox-spec-surge.rcS b/simulators/gem5/configs/boot/natbox-spec-surge.rcS new file mode 100644 index 00000000..4346a622 --- /dev/null +++ b/simulators/gem5/configs/boot/natbox-spec-surge.rcS @@ -0,0 +1,56 @@ +#!/bin/sh +EXTIF=192.168.0.7 +INTIF=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $EXTIF txqueuelen 1000 +ifconfig eth1 $INTIF txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo "1" > /proc/sys/net/ipv4/ip_forward + +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max + +echo "waiting for netserver..." +netcat -c -l -p 8000 + +echo "setting up iptables..." +IPTABLES=/sbin/iptables +EXTIF=eth0 +INTIF=eth1 + +$IPTABLES -P INPUT ACCEPT +$IPTABLES -F INPUT +$IPTABLES -P OUTPUT ACCEPT +$IPTABLES -F OUTPUT +$IPTABLES -P FORWARD DROP +$IPTABLES -F FORWARD +$IPTABLES -t nat -F + +$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT +$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT +$IPTABLES -A FORWARD -j LOG + +$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE + +echo "informing client..." +sleep 5 +echo "server ready" | netcat -c $CLIENT 8000 + +echo "starting bash..." +exec /bin/bash diff --git a/simulators/gem5/configs/boot/netperf-maerts-client.rcS b/simulators/gem5/configs/boot/netperf-maerts-client.rcS new file mode 100644 index 00000000..7766713a --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-maerts-client.rcS @@ -0,0 +1,57 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for server..." +/usr/bin/netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="TCP_MAERTS" +SHORT_ARGS="-l -100k" +LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT +NUMCLNTS=`/sbin/m5 initparam` +[ "$NUMCLNTS" -eq "0" ] && NUMCLNTS=1 + +echo "netperf benchmark... starting $NUMCLNTS..." +lcv=0 + +while [ "$lcv" -lt "$NUMCLNTS" ] +do + echo $LONG + eval $LONG & + ((lcv += 1)) +done + +ckpt=200000000 +((ckpt = ckpt * 12/3 + 600000000)) + +echo "configuring checkpointing at $ckpt..." +/sbin/m5 checkpoint $ckpt 2000000000 +echo "done configuring checkpointing..." +sleep 100000 + diff --git a/simulators/gem5/configs/boot/netperf-rr.rcS b/simulators/gem5/configs/boot/netperf-rr.rcS new file mode 100644 index 00000000..1467c1f6 --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-rr.rcS @@ -0,0 +1,45 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="TCP_RR" +SHORT_ARGS="-l -1k" +LONG_ARGS="-k10000,0 -K10000,0" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 ivlb 1 +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 200000000 2000000000 +/sbin/m5 checkpoint 200000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/netperf-server.rcS b/simulators/gem5/configs/boot/netperf-server.rcS new file mode 100644 index 00000000..95a4ac4c --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-server.rcS @@ -0,0 +1,30 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $SERVER txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo "running netserver..." +/benchmarks/netperf-bin/netserver + +echo -n "signal client to begin..." +sleep 1 +echo "server ready" | netcat -c $CLIENT 8000 +echo "done." + +echo "starting bash..." +exec /bin/bash diff --git a/simulators/gem5/configs/boot/netperf-stream-client.rcS b/simulators/gem5/configs/boot/netperf-stream-client.rcS new file mode 100644 index 00000000..9a2cc0ec --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-stream-client.rcS @@ -0,0 +1,45 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="TCP_STREAM" +SHORT_ARGS="-l -100k" +LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 ivlb 1 +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 200000000 2000000000 +/sbin/m5 checkpoint 200000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/netperf-stream-nt-client.rcS b/simulators/gem5/configs/boot/netperf-stream-nt-client.rcS new file mode 100644 index 00000000..56811552 --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-stream-nt-client.rcS @@ -0,0 +1,45 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="TCP_STREAM" +SHORT_ARGS="-l -100k" +LONG_ARGS="-- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 ivlb 1 +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 200000000 2000000000 +/sbin/m5 checkpoint 200000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/netperf-stream-udp-client.rcS b/simulators/gem5/configs/boot/netperf-stream-udp-client.rcS new file mode 100644 index 00000000..4acb4243 --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-stream-udp-client.rcS @@ -0,0 +1,45 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="UDP_STREAM" +SHORT_ARGS="-l 2 -- -m 16384 -M 16384 -s 262144 -S 262144" +#LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +#echo "netperf benchmark" +#echo $LONG +#/sbin/m5 ivlb 1 +#/sbin/m5 resetstats +#/sbin/m5 dumpresetstats 200000000 2000000000 +#/sbin/m5 checkpoint 200000000 2000000000 +#eval $LONG +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/netperf-stream-udp-local.rcS b/simulators/gem5/configs/boot/netperf-stream-udp-local.rcS new file mode 100644 index 00000000..ccd7654e --- /dev/null +++ b/simulators/gem5/configs/boot/netperf-stream-udp-local.rcS @@ -0,0 +1,22 @@ +#!/bin/sh +SERVER=127.0.0.1 +CLIENT=127.0.0.1 + +echo "setting up network..." +ifconfig lo 127.0.0.1 + +BINARY=/benchmarks/netperf-bin/netperf +TEST="UDP_STREAM" +SHORT_ARGS="-l 2 -- -m 4096" + +echo "running netserver..." +/benchmarks/netperf-bin/netserver + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" + +echo "starting test..." +echo $SHORT +eval $SHORT + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-client-dbench.rcS b/simulators/gem5/configs/boot/nfs-client-dbench.rcS new file mode 100644 index 00000000..29b5043b --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-client-dbench.rcS @@ -0,0 +1,59 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "10" > /proc/sys/vm/dirty_writeback_centisecs +echo "done." + +echo -n "starting nfs client..." +/sbin/portmap & +/sbin/lockd & +echo "done." + +echo -n "waiting for server..." +/usr/bin/netcat -c -l -p 8000 + +echo -n "mounting remote share..." +mkdir /nfs +mount 10.0.0.1:/nfs /nfs +echo "done." + +cd /nfs + +initparam=`m5 initparam` + +if test X$initparam == X0; then + /sbin/m5 checkpoint 100000000 2000000000 + dd if=/dev/zero of=foo bs=1024k count=512 +else + /sbin/m5 checkpoint 1000000000 2000000000 + /benchmarks/dbench/dbench $initparam +fi + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-client-nhfsstone.rcS b/simulators/gem5/configs/boot/nfs-client-nhfsstone.rcS new file mode 100755 index 00000000..c59655a4 --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-client-nhfsstone.rcS @@ -0,0 +1,49 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "starting nfs client..." +/sbin/portmap & +/sbin/lockd & +echo "done." + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +echo -n "mounting remote share..." +mkdir /nfs +mount 10.0.0.1:/nfs /nfs +echo "done." + +/sbin/m5 checkpoint 8000000000 2000000000 +/sbin/nhfsstone /nfs + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-client-smallb.rcS b/simulators/gem5/configs/boot/nfs-client-smallb.rcS new file mode 100755 index 00000000..375da1f5 --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-client-smallb.rcS @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "starting nfs client..." +/sbin/portmap & +/sbin/lockd & +echo "done." + +echo -n "waiting for server..." +/usr/bin/netcat -c -l -p 8000 + +echo -n "mounting remote share..." +mkdir /nfs +mount -o rsize=1460,wsize=1460 10.0.0.1:/nfs /nfs +echo "done." + +/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-client-tcp-smallb.rcS b/simulators/gem5/configs/boot/nfs-client-tcp-smallb.rcS new file mode 100755 index 00000000..b71ca0bf --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-client-tcp-smallb.rcS @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "starting nfs client..." +/sbin/portmap & +/sbin/lockd & +echo "done." + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +echo -n "mounting remote share..." +mkdir /nfs +mount -o rsize=1460,wsize=1460,tcp 10.0.0.1:/nfs /nfs +echo "done." + +/usr/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-client-tcp.rcS b/simulators/gem5/configs/boot/nfs-client-tcp.rcS new file mode 100755 index 00000000..e707ef25 --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-client-tcp.rcS @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "starting nfs client..." +/sbin/portmap & +/sbin/lockd & +echo "done." + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +echo -n "mounting remote share..." +mkdir /nfs +mount -o tcp 10.0.0.1:/nfs /nfs +echo "done." + +/usr/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-client.rcS b/simulators/gem5/configs/boot/nfs-client.rcS new file mode 100755 index 00000000..f3fbe046 --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-client.rcS @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "starting nfs client..." +/sbin/portmap & +/sbin/lockd & +echo "done." + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +echo -n "mounting remote share..." +mkdir /nfs +mount 10.0.0.1:/nfs /nfs +echo "done." + +/usr/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs + +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/nfs-server-nhfsstone.rcS b/simulators/gem5/configs/boot/nfs-server-nhfsstone.rcS new file mode 100755 index 00000000..7fa44a5f --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-server-nhfsstone.rcS @@ -0,0 +1,66 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.1 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +#if [ ! -x /dev/sda ] +#then +# mknod /dev/sda b 8 0 +# mknod /dev/sda1 b 8 1 +#fi + +/sbin/insmod /modules/scsi_debug.ko dev_size_mb=80 + +echo -n "creating partition and formatting..." +/sbin/mke2fs -F /dev/sda +mkdir /nfs +/bin/mount /dev/sda /nfs +chmod a+rwx /nfs +echo "done." + +echo "/nfs 10.0.0.0/255.0.0.0(rw,sync,no_root_squash)" > /etc/exports +echo -n "starting nfs kernel server..." +/sbin/portmap +/sbin/lockd +/sbin/statd +/sbin/nfsd 8 +/sbin/mountd +echo "done." + +echo "Exporting shares..." +/sbin/exportfs -r -v + +echo -n "signal client to mount..." +sleep 5 +echo "server ready" | netcat -c 10.0.0.2 8000 +echo "done." + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/nfs-server.rcS b/simulators/gem5/configs/boot/nfs-server.rcS new file mode 100755 index 00000000..7314d06c --- /dev/null +++ b/simulators/gem5/configs/boot/nfs-server.rcS @@ -0,0 +1,68 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 10.0.0.1 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +#if [ ! -x /dev/sda ] +#then +# mknod /dev/sda b 8 0 +# mknod /dev/sda1 b 8 1 +#fi + +/sbin/insmod /modules/scsi_debug.ko dev_size_mb=768 + +echo -n "creating partition and formatting..." +#echo "1,767,L" > /tmp/sfdisk.run +#/usr/sbin/sfdisk -uM --force /dev/sda < /tmp/sfdisk.run +/sbin/mke2fs -F /dev/sda +mkdir /nfs +/bin/mount /dev/sda /nfs +chmod a+rwx /nfs +#/usr/sbin/sfdisk -uM -l /dev/sda +echo "done." + +echo "/nfs 10.0.0.0/255.0.0.0(rw,sync,no_root_squash)" > /etc/exports +echo -n "starting nfs kernel server..." +/sbin/portmap +/sbin/lockd +/sbin/statd +/sbin/nfsd 15 +/sbin/mountd +echo "done." + +echo "Exporting shares..." +/sbin/exportfs -r -v + +echo -n "signal client to mount..." +echo "server ready" | netcat -c 10.0.0.2 8000 +echo "done." + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/null.rcS b/simulators/gem5/configs/boot/null.rcS new file mode 100644 index 00000000..e69de29b diff --git a/simulators/gem5/configs/boot/ping-client.rcS b/simulators/gem5/configs/boot/ping-client.rcS new file mode 100644 index 00000000..a147fb24 --- /dev/null +++ b/simulators/gem5/configs/boot/ping-client.rcS @@ -0,0 +1,25 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $CLIENT txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "waiting for server..." +netcat -c -l -p 8000 + +ping -c 5 $SERVER +/sbin/m5 exit diff --git a/simulators/gem5/configs/boot/ping-server.rcS b/simulators/gem5/configs/boot/ping-server.rcS new file mode 100644 index 00000000..311c8021 --- /dev/null +++ b/simulators/gem5/configs/boot/ping-server.rcS @@ -0,0 +1,26 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $SERVER txqueuelen 1000 + +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem +echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem +echo "262143" > /proc/sys/net/core/rmem_max +echo "262143" > /proc/sys/net/core/wmem_max +echo "262143" > /proc/sys/net/core/rmem_default +echo "262143" > /proc/sys/net/core/wmem_default +echo "262143" > /proc/sys/net/core/optmem_max +echo "100000" > /proc/sys/net/core/netdev_max_backlog + +echo -n "signal client to begin..." +echo "server ready" | netcat -c $CLIENT 8000 +echo "done." + +echo "starting bash..." +exec /bin/bash diff --git a/simulators/gem5/configs/boot/setup b/simulators/gem5/configs/boot/setup new file mode 100644 index 00000000..842e50a4 --- /dev/null +++ b/simulators/gem5/configs/boot/setup @@ -0,0 +1,37 @@ +ifconfig eth1 mtu 9000 txqueuelen 1000 up + +### IPV4 specific settings +# turns TCP timestamp support off, default 1, reduces CPU use +echo "0" > /proc/sys/net/ipv4/tcp_timestamps + +# turn SACK support off, default on +echo "0" > /proc/sys/net/ipv4/tcp_sack + +# sets min/default/max TCP read buffer, default 4096 87380 174760 +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem + +# sets min/pressure/max TCP write buffer, default 4096 16384 131072 +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem + +# sets min/pressure/max TCP buffer space, default 31744 32256 32768 +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem + +### CORE settings (mostly for socket and UDP effect) +# maximum receive socket buffer size, default 131071 +echo "524287" > /proc/sys/net/core/rmem_max + +# maximum send socket buffer size, default 131071 +echo "524287" > /proc/sys/net/core/wmem_max + +# default receive socket buffer size, default 65535 +echo "524287" > /proc/sys/net/core/rmem_default + +# default send socket buffer size, default 65535 +echo "524287" > /proc/sys/net/core/wmem_default + +# maximum amount of option memory buffers, default 10240 +echo "524287" > /proc/sys/net/core/optmem_max + +# number of unprocessed input packets before kernel starts dropping them, +# default 300 +echo "300000" > /proc/sys/net/core/netdev_max_backlog diff --git a/simulators/gem5/configs/boot/spec-surge-client.rcS b/simulators/gem5/configs/boot/spec-surge-client.rcS new file mode 100644 index 00000000..0dd2ba7d --- /dev/null +++ b/simulators/gem5/configs/boot/spec-surge-client.rcS @@ -0,0 +1,45 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 192.168.0.10 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo "waiting for server..." +netcat -c -l -p 8000 + +echo -n "running surge client..." +/bin/bash -c "cd /benchmarks/surge && ./spec-m5 1 20 1 192.168.0.1 5 40000 1000000000 1000" +echo "done." + +echo -n "halting machine" +m5 exit + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/spec-surge-server.rcS b/simulators/gem5/configs/boot/spec-surge-server.rcS new file mode 100755 index 00000000..89a3fb4f --- /dev/null +++ b/simulators/gem5/configs/boot/spec-surge-server.rcS @@ -0,0 +1,53 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000 +/sbin/ifconfig eth0:1 192.168.0.2 txqueuelen 1000 +/sbin/ifconfig eth0:2 192.168.0.3 txqueuelen 1000 +/sbin/ifconfig eth0:3 192.168.0.4 txqueuelen 1000 +/sbin/ifconfig eth0:4 192.168.0.5 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "mounting file set..." +mkdir -p /z/htdocs +mount /dev/hdb1 /z/htdocs +echo "done." + +echo -n "starting httpd..." +/usr/sbin/apache2 -f /etc/apache2/httpd.conf -k start +sleep 2 +cat /usr/share/apache2/logs/error_log +echo "done." + +echo "notifying client..." +echo "server ready" | netcat -c 192.168.0.10 8000 +echo "done" + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/surge-client.rcS b/simulators/gem5/configs/boot/surge-client.rcS new file mode 100755 index 00000000..ba7d87f6 --- /dev/null +++ b/simulators/gem5/configs/boot/surge-client.rcS @@ -0,0 +1,44 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 192.168.0.10 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo "waiting for server..." +netcat -c -l -p 8000 + +echo -n "running surge client..." +/bin/bash -c "cd /benchmarks/specsurge && ./Surge 2 100 1 192.168.0.1 5" +echo "done." + +echo -n "halting machine" +m5 exit + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/boot/surge-server.rcS b/simulators/gem5/configs/boot/surge-server.rcS new file mode 100755 index 00000000..140c02fb --- /dev/null +++ b/simulators/gem5/configs/boot/surge-server.rcS @@ -0,0 +1,52 @@ +#!/bin/sh +# +# /etc/init.d/rcS +# + + +echo -n "mounting swap..." +/sbin/swapon /dev/hdc +echo "done." + +echo -n "setting up network..." +/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000 +/sbin/ifconfig eth0:1 192.168.0.2 txqueuelen 1000 +/sbin/ifconfig eth0:2 192.168.0.3 txqueuelen 1000 +/sbin/ifconfig eth0:3 192.168.0.4 txqueuelen 1000 +/sbin/ifconfig eth0:4 192.168.0.5 txqueuelen 1000 +/sbin/ifconfig lo 127.0.0.1 + +echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle +echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse +echo "1" > /proc/sys/net/ipv4/tcp_window_scaling +echo "0" > /proc/sys/net/ipv4/tcp_timestamps +echo "0" > /proc/sys/net/ipv4/tcp_sack +echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout +echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog +echo "262144" > /proc/sys/net/ipv4/ip_conntrack_max +echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem +echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem +echo "524287" > /proc/sys/net/core/rmem_max +echo "524287" > /proc/sys/net/core/wmem_max +echo "524287" > /proc/sys/net/core/optmem_max +echo "300000" > /proc/sys/net/core/netdev_max_backlog +echo "131072" > /proc/sys/fs/file-max +echo "done." + +echo -n "mounting file set..." +mkdir -p /z/htdocs +mount /dev/hdb1 /z/htdocs +echo "done." + +echo -n "starting httpd..." +/usr/sbin/apache2 -f /etc/apache2/httpd.conf -k start +sleep 2 +cat /usr/share/apache2/logs/error_log +echo "done." + +echo "server ready" | netcat -c 192.168.10 8000 + +echo -n "starting bash shell..." +/bin/bash diff --git a/simulators/gem5/configs/common/Benchmarks.py b/simulators/gem5/configs/common/Benchmarks.py new file mode 100644 index 00000000..41d5435f --- /dev/null +++ b/simulators/gem5/configs/common/Benchmarks.py @@ -0,0 +1,126 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +from SysPaths import script, disk, binary +from os import environ as env +from m5.defines import buildEnv + +class SysConfig: + def __init__(self, script=None, mem=None, disk=None): + self.scriptname = script + self.diskname = disk + self.memsize = mem + + def script(self): + if self.scriptname: + return script(self.scriptname) + else: + return '' + + def mem(self): + if self.memsize: + return self.memsize + else: + return '128MB' + + def disk(self): + if self.diskname: + return disk(self.diskname) + elif buildEnv['TARGET_ISA'] == 'alpha': + return env.get('LINUX_IMAGE', disk('linux-latest.img')) + elif buildEnv['TARGET_ISA'] == 'x86': + return env.get('LINUX_IMAGE', disk('x86root.img')) + elif buildEnv['TARGET_ISA'] == 'arm': + return env.get('LINUX_IMAGE', disk('linux-arm-ael.img')) + else: + print "Don't know what default disk image to use for %s ISA" % \ + buildEnv['TARGET_ISA'] + exit(1) + +# Benchmarks are defined as a key in a dict which is a list of SysConfigs +# The first defined machine is the test system, the others are driving systems + +Benchmarks = { + 'PovrayBench': [SysConfig('povray-bench.rcS', '512MB', 'povray.img')], + 'PovrayAutumn': [SysConfig('povray-autumn.rcS', '512MB', 'povray.img')], + + 'NetperfStream': [SysConfig('netperf-stream-client.rcS'), + SysConfig('netperf-server.rcS')], + 'NetperfStreamUdp': [SysConfig('netperf-stream-udp-client.rcS'), + SysConfig('netperf-server.rcS')], + 'NetperfUdpLocal': [SysConfig('netperf-stream-udp-local.rcS')], + 'NetperfStreamNT': [SysConfig('netperf-stream-nt-client.rcS'), + SysConfig('netperf-server.rcS')], + 'NetperfMaerts': [SysConfig('netperf-maerts-client.rcS'), + SysConfig('netperf-server.rcS')], + 'SurgeStandard': [SysConfig('surge-server.rcS', '512MB'), + SysConfig('surge-client.rcS', '256MB')], + 'SurgeSpecweb': [SysConfig('spec-surge-server.rcS', '512MB'), + SysConfig('spec-surge-client.rcS', '256MB')], + 'Nhfsstone': [SysConfig('nfs-server-nhfsstone.rcS', '512MB'), + SysConfig('nfs-client-nhfsstone.rcS')], + 'Nfs': [SysConfig('nfs-server.rcS', '900MB'), + SysConfig('nfs-client-dbench.rcS')], + 'NfsTcp': [SysConfig('nfs-server.rcS', '900MB'), + SysConfig('nfs-client-tcp.rcS')], + 'IScsiInitiator': [SysConfig('iscsi-client.rcS', '512MB'), + SysConfig('iscsi-server.rcS', '512MB')], + 'IScsiTarget': [SysConfig('iscsi-server.rcS', '512MB'), + SysConfig('iscsi-client.rcS', '512MB')], + 'Validation': [SysConfig('iscsi-server.rcS', '512MB'), + SysConfig('iscsi-client.rcS', '512MB')], + 'Ping': [SysConfig('ping-server.rcS',), + SysConfig('ping-client.rcS')], + + 'ValAccDelay': [SysConfig('devtime.rcS', '512MB')], + 'ValAccDelay2': [SysConfig('devtimewmr.rcS', '512MB')], + 'ValMemLat': [SysConfig('micro_memlat.rcS', '512MB')], + 'ValMemLat2MB': [SysConfig('micro_memlat2mb.rcS', '512MB')], + 'ValMemLat8MB': [SysConfig('micro_memlat8mb.rcS', '512MB')], + 'ValMemLat': [SysConfig('micro_memlat8.rcS', '512MB')], + 'ValTlbLat': [SysConfig('micro_tlblat.rcS', '512MB')], + 'ValSysLat': [SysConfig('micro_syscall.rcS', '512MB')], + 'ValCtxLat': [SysConfig('micro_ctx.rcS', '512MB')], + 'ValStream': [SysConfig('micro_stream.rcS', '512MB')], + 'ValStreamScale': [SysConfig('micro_streamscale.rcS', '512MB')], + 'ValStreamCopy': [SysConfig('micro_streamcopy.rcS', '512MB')], + + 'MutexTest': [SysConfig('mutex-test.rcS', '128MB')], + 'ArmAndroid-GB': [SysConfig('null.rcS', '256MB', + 'ARMv7a-Gingerbread-Android.SMP.mouse.nolock.clean.img')], + 'bbench-gb': [SysConfig('bbench-gb.rcS', '256MB', + 'ARMv7a-Gingerbread-Android.SMP.mouse.nolock.img')], + 'ArmAndroid-ICS': [SysConfig('null.rcS', '256MB', + 'ARMv7a-ICS-Android.SMP.nolock.clean.img')], + 'bbench-ics': [SysConfig('bbench-ics.rcS', '256MB', + 'ARMv7a-ICS-Android.SMP.nolock.img')] +} + +benchs = Benchmarks.keys() +benchs.sort() +DefinedBenchmarks = ", ".join(benchs) diff --git a/simulators/gem5/configs/common/CacheConfig.py b/simulators/gem5/configs/common/CacheConfig.py new file mode 100644 index 00000000..bc724f65 --- /dev/null +++ b/simulators/gem5/configs/common/CacheConfig.py @@ -0,0 +1,79 @@ +# Copyright (c) 2010 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Lisa Hsu + +# Configure the M5 cache hierarchy config in one place +# + +import m5 +from m5.objects import * +from Caches import * +from O3_ARM_v7a import * + +def config_cache(options, system): + if options.l2cache: + if options.cpu_type == "arm_detailed": + system.l2 = O3_ARM_v7aL2(size = options.l2_size, assoc = options.l2_assoc, + block_size=options.cacheline_size) + else: + system.l2 = L2Cache(size = options.l2_size, assoc = options.l2_assoc, + block_size=options.cacheline_size) + + system.tol2bus = CoherentBus() + system.l2.cpu_side = system.tol2bus.master + system.l2.mem_side = system.membus.slave + + for i in xrange(options.num_cpus): + if options.caches: + if options.cpu_type == "arm_detailed": + icache = O3_ARM_v7a_ICache(size = options.l1i_size, + assoc = options.l1i_assoc, + block_size=options.cacheline_size) + dcache = O3_ARM_v7a_DCache(size = options.l1d_size, + assoc = options.l1d_assoc, + block_size=options.cacheline_size) + else: + icache = L1Cache(size = options.l1i_size, + assoc = options.l1i_assoc, + block_size=options.cacheline_size) + dcache = L1Cache(size = options.l1d_size, + assoc = options.l1d_assoc, + block_size=options.cacheline_size) + + if buildEnv['TARGET_ISA'] == 'x86': + system.cpu[i].addPrivateSplitL1Caches(icache, dcache, + PageTableWalkerCache(), + PageTableWalkerCache()) + else: + system.cpu[i].addPrivateSplitL1Caches(icache, dcache) + system.cpu[i].createInterruptController() + if options.l2cache: + system.cpu[i].connectAllPorts(system.tol2bus, system.membus) + else: + system.cpu[i].connectAllPorts(system.membus) + + return system diff --git a/simulators/gem5/configs/common/Caches.py b/simulators/gem5/configs/common/Caches.py new file mode 100644 index 00000000..0be8001d --- /dev/null +++ b/simulators/gem5/configs/common/Caches.py @@ -0,0 +1,63 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Lisa Hsu + +from m5.objects import * + +class L1Cache(BaseCache): + assoc = 2 + block_size = 64 + latency = '1ns' + mshrs = 10 + tgts_per_mshr = 20 + is_top_level = True + +class L2Cache(BaseCache): + assoc = 8 + block_size = 64 + latency = '10ns' + mshrs = 20 + tgts_per_mshr = 12 + +class PageTableWalkerCache(BaseCache): + assoc = 2 + block_size = 64 + latency = '1ns' + mshrs = 10 + size = '1kB' + tgts_per_mshr = 12 + is_top_level = True + +class IOCache(BaseCache): + assoc = 8 + block_size = 64 + latency = '10ns' + mshrs = 20 + size = '1kB' + tgts_per_mshr = 12 + forward_snoops = False + is_top_level = True diff --git a/simulators/gem5/configs/common/FSConfig.py b/simulators/gem5/configs/common/FSConfig.py new file mode 100644 index 00000000..0e26242a --- /dev/null +++ b/simulators/gem5/configs/common/FSConfig.py @@ -0,0 +1,561 @@ +# Copyright (c) 2010-2012 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. +# Copyright (c) 2006-2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Kevin Lim + +from m5.objects import * +from Benchmarks import * +from m5.util import convert + +class CowIdeDisk(IdeDisk): + image = CowDiskImage(child=RawDiskImage(read_only=True), + read_only=False) + + def childImage(self, ci): + self.image.child.image_file = ci + +class MemBus(CoherentBus): + badaddr_responder = BadAddr() + default = Self.badaddr_responder.pio + + +def makeLinuxAlphaSystem(mem_mode, mdesc = None): + IO_address_space_base = 0x80000000000 + class BaseTsunami(Tsunami): + ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) + ide = IdeController(disks=[Parent.disk0, Parent.disk2], + pci_func=0, pci_dev=0, pci_bus=0) + + self = LinuxAlphaSystem() + if not mdesc: + # generic system + mdesc = SysConfig() + self.readfile = mdesc.script() + self.iobus = NoncoherentBus() + self.membus = MemBus() + # By default the bridge responds to all addresses above the I/O + # base address (including the PCI config space) + self.bridge = Bridge(delay='50ns', nack_delay='4ns', + ranges = [AddrRange(IO_address_space_base, Addr.max)]) + self.physmem = SimpleMemory(range = AddrRange(mdesc.mem())) + self.bridge.master = self.iobus.slave + self.bridge.slave = self.membus.master + self.physmem.port = self.membus.master + self.disk0 = CowIdeDisk(driveID='master') + self.disk2 = CowIdeDisk(driveID='master') + self.disk0.childImage(mdesc.disk()) + self.disk2.childImage(disk('linux-bigswap2.img')) + self.tsunami = BaseTsunami() + self.tsunami.attachIO(self.iobus) + self.tsunami.ide.pio = self.iobus.master + self.tsunami.ide.config = self.iobus.master + self.tsunami.ide.dma = self.iobus.slave + self.tsunami.ethernet.pio = self.iobus.master + self.tsunami.ethernet.config = self.iobus.master + self.tsunami.ethernet.dma = self.iobus.slave + self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(), + read_only = True)) + self.intrctrl = IntrControl() + self.mem_mode = mem_mode + self.terminal = Terminal() + self.kernel = binary('vmlinux') + self.pal = binary('ts_osfpal') + self.console = binary('console') + self.boot_osflags = 'root=/dev/hda1 console=ttyS0' + + self.system_port = self.membus.slave + + return self + +def makeLinuxAlphaRubySystem(mem_mode, mdesc = None): + class BaseTsunami(Tsunami): + ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) + ide = IdeController(disks=[Parent.disk0, Parent.disk2], + pci_func=0, pci_dev=0, pci_bus=0) + + physmem = SimpleMemory(range = AddrRange(mdesc.mem())) + self = LinuxAlphaSystem(physmem = physmem) + if not mdesc: + # generic system + mdesc = SysConfig() + self.readfile = mdesc.script() + + # Create pio bus to connect all device pio ports to rubymem's pio port + self.piobus = NoncoherentBus() + + # + # Pio functional accesses from devices need direct access to memory + # RubyPort currently does support functional accesses. Therefore provide + # the piobus a direct connection to physical memory + # + self.piobus.master = physmem.port + + self.disk0 = CowIdeDisk(driveID='master') + self.disk2 = CowIdeDisk(driveID='master') + self.disk0.childImage(mdesc.disk()) + self.disk2.childImage(disk('linux-bigswap2.img')) + self.tsunami = BaseTsunami() + self.tsunami.attachIO(self.piobus) + self.tsunami.ide.pio = self.piobus.master + self.tsunami.ide.config = self.piobus.master + self.tsunami.ethernet.pio = self.piobus.master + self.tsunami.ethernet.config = self.piobus.master + + # + # Store the dma devices for later connection to dma ruby ports. + # Append an underscore to dma_devices to avoid the SimObjectVector check. + # + self._dma_ports = [self.tsunami.ide.dma, self.tsunami.ethernet.dma] + + self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(), + read_only = True)) + self.intrctrl = IntrControl() + self.mem_mode = mem_mode + self.terminal = Terminal() + self.kernel = binary('vmlinux') + self.pal = binary('ts_osfpal') + self.console = binary('console') + self.boot_osflags = 'root=/dev/hda1 console=ttyS0' + + return self + +def makeSparcSystem(mem_mode, mdesc = None): + # Constants from iob.cc and uart8250.cc + iob_man_addr = 0x9800000000 + uart_pio_size = 8 + + class CowMmDisk(MmDisk): + image = CowDiskImage(child=RawDiskImage(read_only=True), + read_only=False) + + def childImage(self, ci): + self.image.child.image_file = ci + + self = SparcSystem() + if not mdesc: + # generic system + mdesc = SysConfig() + self.readfile = mdesc.script() + self.iobus = NoncoherentBus() + self.membus = MemBus() + self.bridge = Bridge(delay='50ns', nack_delay='4ns') + self.t1000 = T1000() + self.t1000.attachOnChipIO(self.membus) + self.t1000.attachIO(self.iobus) + self.physmem = SimpleMemory(range = AddrRange(Addr('1MB'), size = '64MB'), + zero = True) + self.physmem2 = SimpleMemory(range = AddrRange(Addr('2GB'), size ='256MB'), + zero = True) + self.bridge.master = self.iobus.slave + self.bridge.slave = self.membus.master + self.physmem.port = self.membus.master + self.physmem2.port = self.membus.master + self.rom.port = self.membus.master + self.nvram.port = self.membus.master + self.hypervisor_desc.port = self.membus.master + self.partition_desc.port = self.membus.master + self.intrctrl = IntrControl() + self.disk0 = CowMmDisk() + self.disk0.childImage(disk('disk.s10hw2')) + self.disk0.pio = self.iobus.master + + # The puart0 and hvuart are placed on the IO bus, so create ranges + # for them. The remaining IO range is rather fragmented, so poke + # holes for the iob and partition descriptors etc. + self.bridge.ranges = \ + [ + AddrRange(self.t1000.puart0.pio_addr, + self.t1000.puart0.pio_addr + uart_pio_size - 1), + AddrRange(self.disk0.pio_addr, + self.t1000.fake_jbi.pio_addr + + self.t1000.fake_jbi.pio_size - 1), + AddrRange(self.t1000.fake_clk.pio_addr, + iob_man_addr - 1), + AddrRange(self.t1000.fake_l2_1.pio_addr, + self.t1000.fake_ssi.pio_addr + + self.t1000.fake_ssi.pio_size - 1), + AddrRange(self.t1000.hvuart.pio_addr, + self.t1000.hvuart.pio_addr + uart_pio_size - 1) + ] + self.reset_bin = binary('reset_new.bin') + self.hypervisor_bin = binary('q_new.bin') + self.openboot_bin = binary('openboot_new.bin') + self.nvram_bin = binary('nvram1') + self.hypervisor_desc_bin = binary('1up-hv.bin') + self.partition_desc_bin = binary('1up-md.bin') + + self.system_port = self.membus.slave + + return self + +def makeArmSystem(mem_mode, machine_type, mdesc = None, bare_metal=False): + assert machine_type + + if bare_metal: + self = ArmSystem() + else: + self = LinuxArmSystem() + + if not mdesc: + # generic system + mdesc = SysConfig() + + self.readfile = mdesc.script() + self.iobus = NoncoherentBus() + self.membus = MemBus() + self.membus.badaddr_responder.warn_access = "warn" + self.bridge = Bridge(delay='50ns', nack_delay='4ns') + self.bridge.master = self.iobus.slave + self.bridge.slave = self.membus.master + + self.mem_mode = mem_mode + + if machine_type == "RealView_PBX": + self.realview = RealViewPBX() + elif machine_type == "RealView_EB": + self.realview = RealViewEB() + elif machine_type == "VExpress_ELT": + self.realview = VExpress_ELT() + elif machine_type == "VExpress_EMM": + self.realview = VExpress_EMM() + self.load_addr_mask = 0xffffffff + else: + print "Unknown Machine Type" + sys.exit(1) + + self.cf0 = CowIdeDisk(driveID='master') + self.cf0.childImage(mdesc.disk()) + # default to an IDE controller rather than a CF one + # assuming we've got one + try: + self.realview.ide.disks = [self.cf0] + except: + self.realview.cf_ctrl.disks = [self.cf0] + + if bare_metal: + # EOT character on UART will end the simulation + self.realview.uart.end_on_eot = True + self.physmem = SimpleMemory(range = AddrRange(Addr(mdesc.mem())), + zero = True) + else: + self.kernel = binary('vmlinux.arm.smp.fb.2.6.38.8') + self.machine_type = machine_type + if convert.toMemorySize(mdesc.mem()) > int(self.realview.max_mem_size): + print "The currently selected ARM platforms doesn't support" + print " the amount of DRAM you've selected. Please try" + print " another platform" + sys.exit(1) + + boot_flags = 'earlyprintk console=ttyAMA0 lpj=19988480 norandmaps ' + \ + 'rw loglevel=8 mem=%s root=/dev/sda1' % mdesc.mem() + + self.physmem = SimpleMemory(range = + AddrRange(self.realview.mem_start_addr, + size = mdesc.mem()), + conf_table_reported = True) + self.realview.setupBootLoader(self.membus, self, binary) + self.gic_cpu_addr = self.realview.gic.cpu_addr + self.flags_addr = self.realview.realview_io.pio_addr + 0x30 + + if mdesc.disk().lower().count('android'): + boot_flags += " init=/init " + self.boot_osflags = boot_flags + + self.physmem.port = self.membus.master + self.realview.attachOnChipIO(self.membus, self.bridge) + self.realview.attachIO(self.iobus) + self.intrctrl = IntrControl() + self.terminal = Terminal() + self.vncserver = VncServer() + + self.system_port = self.membus.slave + + return self + + +def makeLinuxMipsSystem(mem_mode, mdesc = None): + class BaseMalta(Malta): + ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) + ide = IdeController(disks=[Parent.disk0, Parent.disk2], + pci_func=0, pci_dev=0, pci_bus=0) + + self = LinuxMipsSystem() + if not mdesc: + # generic system + mdesc = SysConfig() + self.readfile = mdesc.script() + self.iobus = NoncoherentBus() + self.membus = MemBus() + self.bridge = Bridge(delay='50ns', nack_delay='4ns') + self.physmem = SimpleMemory(range = AddrRange('1GB')) + self.bridge.master = self.iobus.slave + self.bridge.slave = self.membus.master + self.physmem.port = self.membus.master + self.disk0 = CowIdeDisk(driveID='master') + self.disk2 = CowIdeDisk(driveID='master') + self.disk0.childImage(mdesc.disk()) + self.disk2.childImage(disk('linux-bigswap2.img')) + self.malta = BaseMalta() + self.malta.attachIO(self.iobus) + self.malta.ide.pio = self.iobus.master + self.malta.ide.config = self.iobus.master + self.malta.ide.dma = self.iobus.slave + self.malta.ethernet.pio = self.iobus.master + self.malta.ethernet.config = self.iobus.master + self.malta.ethernet.dma = self.iobus.slave + self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(), + read_only = True)) + self.intrctrl = IntrControl() + self.mem_mode = mem_mode + self.terminal = Terminal() + self.kernel = binary('mips/vmlinux') + self.console = binary('mips/console') + self.boot_osflags = 'root=/dev/hda1 console=ttyS0' + + self.system_port = self.membus.slave + + return self + +def x86IOAddress(port): + IO_address_space_base = 0x8000000000000000 + return IO_address_space_base + port + +def connectX86ClassicSystem(x86_sys, numCPUs): + # Constants similar to x86_traits.hh + IO_address_space_base = 0x8000000000000000 + pci_config_address_space_base = 0xc000000000000000 + interrupts_address_space_base = 0xa000000000000000 + APIC_range_size = 1 << 12; + + x86_sys.membus = MemBus() + x86_sys.physmem.port = x86_sys.membus.master + + # North Bridge + x86_sys.iobus = NoncoherentBus() + x86_sys.bridge = Bridge(delay='50ns', nack_delay='4ns') + x86_sys.bridge.master = x86_sys.iobus.slave + x86_sys.bridge.slave = x86_sys.membus.master + # Allow the bridge to pass through the IO APIC (two pages), + # everything in the IO address range up to the local APIC, and + # then the entire PCI address space and beyond + x86_sys.bridge.ranges = \ + [ + AddrRange(x86_sys.pc.south_bridge.io_apic.pio_addr, + x86_sys.pc.south_bridge.io_apic.pio_addr + + APIC_range_size - 1), + AddrRange(IO_address_space_base, + interrupts_address_space_base - 1), + AddrRange(pci_config_address_space_base, + Addr.max) + ] + + # Create a bridge from the IO bus to the memory bus to allow access to + # the local APIC (two pages) + x86_sys.apicbridge = Bridge(delay='50ns', nack_delay='4ns') + x86_sys.apicbridge.slave = x86_sys.iobus.master + x86_sys.apicbridge.master = x86_sys.membus.slave + x86_sys.apicbridge.ranges = [AddrRange(interrupts_address_space_base, + interrupts_address_space_base + + numCPUs * APIC_range_size + - 1)] + + # connect the io bus + x86_sys.pc.attachIO(x86_sys.iobus) + + x86_sys.system_port = x86_sys.membus.slave + +def connectX86RubySystem(x86_sys): + # North Bridge + x86_sys.piobus = NoncoherentBus() + + # + # Pio functional accesses from devices need direct access to memory + # RubyPort currently does support functional accesses. Therefore provide + # the piobus a direct connection to physical memory + # + x86_sys.piobus.master = x86_sys.physmem.port + # add the ide to the list of dma devices that later need to attach to + # dma controllers + x86_sys._dma_ports = [x86_sys.pc.south_bridge.ide.dma] + x86_sys.pc.attachIO(x86_sys.piobus, x86_sys._dma_ports) + + +def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False): + if self == None: + self = X86System() + + if not mdesc: + # generic system + mdesc = SysConfig() + self.readfile = mdesc.script() + + self.mem_mode = mem_mode + + # Physical memory + self.physmem = SimpleMemory(range = AddrRange(mdesc.mem())) + + # Platform + self.pc = Pc() + + # Create and connect the busses required by each memory system + if Ruby: + connectX86RubySystem(self) + else: + connectX86ClassicSystem(self, numCPUs) + + self.intrctrl = IntrControl() + + # Disks + disk0 = CowIdeDisk(driveID='master') + disk2 = CowIdeDisk(driveID='master') + disk0.childImage(mdesc.disk()) + disk2.childImage(disk('linux-bigswap2.img')) + self.pc.south_bridge.ide.disks = [disk0, disk2] + + # Add in a Bios information structure. + structures = [X86SMBiosBiosInformation()] + self.smbios_table.structures = structures + + # Set up the Intel MP table + base_entries = [] + ext_entries = [] + for i in xrange(numCPUs): + bp = X86IntelMPProcessor( + local_apic_id = i, + local_apic_version = 0x14, + enable = True, + bootstrap = (i == 0)) + base_entries.append(bp) + io_apic = X86IntelMPIOAPIC( + id = numCPUs, + version = 0x11, + enable = True, + address = 0xfec00000) + self.pc.south_bridge.io_apic.apic_id = io_apic.id + base_entries.append(io_apic) + isa_bus = X86IntelMPBus(bus_id = 0, bus_type='ISA') + base_entries.append(isa_bus) + pci_bus = X86IntelMPBus(bus_id = 1, bus_type='PCI') + base_entries.append(pci_bus) + connect_busses = X86IntelMPBusHierarchy(bus_id=0, + subtractive_decode=True, parent_bus=1) + ext_entries.append(connect_busses) + pci_dev4_inta = X86IntelMPIOIntAssignment( + interrupt_type = 'INT', + polarity = 'ConformPolarity', + trigger = 'ConformTrigger', + source_bus_id = 1, + source_bus_irq = 0 + (4 << 2), + dest_io_apic_id = io_apic.id, + dest_io_apic_intin = 16) + base_entries.append(pci_dev4_inta) + def assignISAInt(irq, apicPin): + assign_8259_to_apic = X86IntelMPIOIntAssignment( + interrupt_type = 'ExtInt', + polarity = 'ConformPolarity', + trigger = 'ConformTrigger', + source_bus_id = 0, + source_bus_irq = irq, + dest_io_apic_id = io_apic.id, + dest_io_apic_intin = 0) + base_entries.append(assign_8259_to_apic) + assign_to_apic = X86IntelMPIOIntAssignment( + interrupt_type = 'INT', + polarity = 'ConformPolarity', + trigger = 'ConformTrigger', + source_bus_id = 0, + source_bus_irq = irq, + dest_io_apic_id = io_apic.id, + dest_io_apic_intin = apicPin) + base_entries.append(assign_to_apic) + assignISAInt(0, 2) + assignISAInt(1, 1) + for i in range(3, 15): + assignISAInt(i, i) + self.intel_mp_table.base_entries = base_entries + self.intel_mp_table.ext_entries = ext_entries + +def makeLinuxX86System(mem_mode, numCPUs = 1, mdesc = None, Ruby = False): + self = LinuxX86System() + + # Build up the x86 system and then specialize it for Linux + makeX86System(mem_mode, numCPUs, mdesc, self, Ruby) + + # We assume below that there's at least 1MB of memory. We'll require 2 + # just to avoid corner cases. + assert(self.physmem.range.second.getValue() >= 0x200000) + + self.e820_table.entries = \ + [ + # Mark the first megabyte of memory as reserved + X86E820Entry(addr = 0, size = '1MB', range_type = 2), + # Mark the rest as available + X86E820Entry(addr = 0x100000, + size = '%dB' % (self.physmem.range.second - 0x100000 + 1), + range_type = 1) + ] + + # Command line + self.boot_osflags = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 ' + \ + 'root=/dev/hda1' + return self + + +def makeDualRoot(full_system, testSystem, driveSystem, dumpfile): + self = Root(full_system = full_system) + self.testsys = testSystem + self.drivesys = driveSystem + self.etherlink = EtherLink() + self.etherlink.int0 = Parent.testsys.tsunami.ethernet.interface + self.etherlink.int1 = Parent.drivesys.tsunami.ethernet.interface + + if hasattr(testSystem, 'realview'): + self.etherlink.int0 = Parent.testsys.realview.ethernet.interface + self.etherlink.int1 = Parent.drivesys.realview.ethernet.interface + elif hasattr(testSystem, 'tsunami'): + self.etherlink.int0 = Parent.testsys.tsunami.ethernet.interface + self.etherlink.int1 = Parent.drivesys.tsunami.ethernet.interface + else: + fatal("Don't know how to connect these system together") + + if dumpfile: + self.etherdump = EtherDump(file=dumpfile) + self.etherlink.dump = Parent.etherdump + + return self diff --git a/simulators/gem5/configs/common/O3_ARM_v7a.py b/simulators/gem5/configs/common/O3_ARM_v7a.py new file mode 100644 index 00000000..68fb0c54 --- /dev/null +++ b/simulators/gem5/configs/common/O3_ARM_v7a.py @@ -0,0 +1,196 @@ +# Copyright (c) 2012 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski + + +from m5.objects import * + +# Simple ALU Instructions have a latency of 1 +class O3_ARM_v7a_Simple_Int(FUDesc): + opList = [ OpDesc(opClass='IntAlu', opLat=1) ] + count = 2 + +# Complex ALU instructions have a variable latencies +class O3_ARM_v7a_Complex_Int(FUDesc): + opList = [ OpDesc(opClass='IntMult', opLat=3, issueLat=1), + OpDesc(opClass='IntDiv', opLat=12, issueLat=12), + OpDesc(opClass='IprAccess', opLat=3, issueLat=1) ] + count = 1 + + +# Floating point and SIMD instructions +class O3_ARM_v7a_FP(FUDesc): + opList = [ OpDesc(opClass='SimdAdd', opLat=4), + OpDesc(opClass='SimdAddAcc', opLat=4), + OpDesc(opClass='SimdAlu', opLat=4), + OpDesc(opClass='SimdCmp', opLat=4), + OpDesc(opClass='SimdCvt', opLat=3), + OpDesc(opClass='SimdMisc', opLat=3), + OpDesc(opClass='SimdMult',opLat=5), + OpDesc(opClass='SimdMultAcc',opLat=5), + OpDesc(opClass='SimdShift',opLat=3), + OpDesc(opClass='SimdShiftAcc', opLat=3), + OpDesc(opClass='SimdSqrt', opLat=9), + OpDesc(opClass='SimdFloatAdd',opLat=5), + OpDesc(opClass='SimdFloatAlu',opLat=5), + OpDesc(opClass='SimdFloatCmp', opLat=3), + OpDesc(opClass='SimdFloatCvt', opLat=3), + OpDesc(opClass='SimdFloatDiv', opLat=3), + OpDesc(opClass='SimdFloatMisc', opLat=3), + OpDesc(opClass='SimdFloatMult', opLat=3), + OpDesc(opClass='SimdFloatMultAcc',opLat=1), + OpDesc(opClass='SimdFloatSqrt', opLat=9), + OpDesc(opClass='FloatAdd', opLat=5), + OpDesc(opClass='FloatCmp', opLat=5), + OpDesc(opClass='FloatCvt', opLat=5), + OpDesc(opClass='FloatDiv', opLat=9, issueLat=9), + OpDesc(opClass='FloatSqrt', opLat=33, issueLat=33), + OpDesc(opClass='FloatMult', opLat=4) ] + count = 2 + + +# Load/Store Units +class O3_ARM_v7a_Load(FUDesc): + opList = [ OpDesc(opClass='MemRead',opLat=2) ] + count = 1 + +class O3_ARM_v7a_Store(FUDesc): + opList = [OpDesc(opClass='MemWrite',opLat=2) ] + count = 1 + +# Functional Units for this CPU +class O3_ARM_v7a_FUP(FUPool): + FUList = [O3_ARM_v7a_Simple_Int(), O3_ARM_v7a_Complex_Int(), + O3_ARM_v7a_Load(), O3_ARM_v7a_Store(), O3_ARM_v7a_FP()] + + +class O3_ARM_v7a_3(DerivO3CPU): + predType = "tournament" + localPredictorSize = 64 + localCtrBits = 2 + localHistoryTableSize = 64 + localHistoryBits = 6 + globalPredictorSize = 8192 + globalCtrBits = 2 + globalHistoryBits = 13 + choicePredictorSize = 8192 + choiceCtrBits = 2 + BTBEntries = 2048 + BTBTagSize = 18 + RASSize = 16 + instShiftAmt = 2 + LQEntries = 16 + SQEntries = 16 + LSQDepCheckShift = 0 + LFSTSize = 1024 + SSITSize = 1024 + decodeToFetchDelay = 1 + renameToFetchDelay = 1 + iewToFetchDelay = 1 + commitToFetchDelay = 1 + renameToDecodeDelay = 1 + iewToDecodeDelay = 1 + commitToDecodeDelay = 1 + iewToRenameDelay = 1 + commitToRenameDelay = 1 + commitToIEWDelay = 1 + fetchWidth = 3 + fetchToDecodeDelay = 3 + decodeWidth = 3 + decodeToRenameDelay = 2 + renameWidth = 3 + renameToIEWDelay = 1 + issueToExecuteDelay = 1 + dispatchWidth = 6 + issueWidth = 8 + wbWidth = 8 + wbDepth = 1 + fuPool = O3_ARM_v7a_FUP() + iewToCommitDelay = 1 + renameToROBDelay = 1 + commitWidth = 8 + squashWidth = 8 + trapLatency = 13 + backComSize = 5 + forwardComSize = 5 + numPhysIntRegs = 128 + numPhysFloatRegs = 128 + numIQEntries = 32 + numROBEntries = 40 + + defer_registration= False + +# Instruction Cache +# All latencys assume a 1GHz clock rate, with a faster clock they would be faster +class O3_ARM_v7a_ICache(BaseCache): + latency = '1ns' + block_size = 64 + mshrs = 2 + tgts_per_mshr = 8 + size = '32kB' + assoc = 2 + is_top_level = 'true' + +# Data Cache +# All latencys assume a 1GHz clock rate, with a faster clock they would be faster +class O3_ARM_v7a_DCache(BaseCache): + latency = '2ns' + block_size = 64 + mshrs = 6 + tgts_per_mshr = 8 + size = '32kB' + assoc = 2 + write_buffers = 16 + is_top_level = 'true' + +# TLB Cache +# Use a cache as a L2 TLB +class O3_ARM_v7aWalkCache(BaseCache): + latency = '4ns' + block_size = 64 + mshrs = 6 + tgts_per_mshr = 8 + size = '1kB' + assoc = 8 + write_buffers = 16 + is_top_level = 'true' + + +# L2 Cache +# All latencys assume a 1GHz clock rate, with a faster clock they would be faster +class O3_ARM_v7aL2(BaseCache): + latency = '12ns' + block_size = 64 + mshrs = 16 + tgts_per_mshr = 8 + size = '1MB' + assoc = 16 + write_buffers = 8 + prefetch_on_access = 'true' + # Simple stride prefetcher + prefetcher = StridePrefetcher(degree=8, latency='1.0ns') + diff --git a/simulators/gem5/configs/common/Options.py b/simulators/gem5/configs/common/Options.py new file mode 100644 index 00000000..c625ab17 --- /dev/null +++ b/simulators/gem5/configs/common/Options.py @@ -0,0 +1,181 @@ +# Copyright (c) 2006-2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Lisa Hsu + +import m5 +from m5.defines import buildEnv +from m5.objects import * +from Benchmarks import * + +def addCommonOptions(parser): + # system options + parser.add_option("--cpu-type", type="choice", default="atomic", + choices = ["atomic", "timing", "detailed", "inorder", + "arm_detailed"], + help = "type of cpu to run with") + parser.add_option("--checker", action="store_true"); + parser.add_option("-n", "--num-cpus", type="int", default=1) + parser.add_option("--caches", action="store_true") + parser.add_option("--l2cache", action="store_true") + parser.add_option("--fastmem", action="store_true") + parser.add_option("--clock", action="store", type="string", default='2GHz') + parser.add_option("--num-dirs", type="int", default=1) + parser.add_option("--num-l2caches", type="int", default=1) + parser.add_option("--num-l3caches", type="int", default=1) + parser.add_option("--l1d_size", type="string", default="64kB") + parser.add_option("--l1i_size", type="string", default="32kB") + parser.add_option("--l2_size", type="string", default="2MB") + parser.add_option("--l3_size", type="string", default="16MB") + parser.add_option("--l1d_assoc", type="int", default=2) + parser.add_option("--l1i_assoc", type="int", default=2) + parser.add_option("--l2_assoc", type="int", default=8) + parser.add_option("--l3_assoc", type="int", default=16) + parser.add_option("--cacheline_size", type="int", default=64) + parser.add_option("--ruby", action="store_true") + + # Run duration options + parser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick, + metavar="T", help="Stop after T ticks") + parser.add_option("--maxtime", type="float") + parser.add_option("-I", "--maxinsts", action="store", type="int", + default=None, help="""Total number of instructions to + simulate (default: run forever)""") + parser.add_option("--work-item-id", action="store", type="int", + help="the specific work id for exit & checkpointing") + parser.add_option("--work-begin-cpu-id-exit", action="store", type="int", + help="exit when work starts on the specified cpu") + parser.add_option("--work-end-exit-count", action="store", type="int", + help="exit at specified work end count") + parser.add_option("--work-begin-exit-count", action="store", type="int", + help="exit at specified work begin count") + parser.add_option("--init-param", action="store", type="int", default=0, + help="""Parameter available in simulation with m5 + initparam""") + + # Checkpointing options + ###Note that performing checkpointing via python script files will override + ###checkpoint instructions built into binaries. + parser.add_option("--take-checkpoints", action="store", type="string", + help=" will take checkpoint at cycle M and every N cycles thereafter") + parser.add_option("--max-checkpoints", action="store", type="int", + help="the maximum number of checkpoints to drop", default=5) + parser.add_option("--checkpoint-dir", action="store", type="string", + help="Place all checkpoints in this absolute directory") + parser.add_option("-r", "--checkpoint-restore", action="store", type="int", + help="restore from checkpoint ") + parser.add_option("--checkpoint-at-end", action="store_true", + help="take a checkpoint at end of run") + parser.add_option("--work-begin-checkpoint-count", action="store", type="int", + help="checkpoint at specified work begin count") + parser.add_option("--work-end-checkpoint-count", action="store", type="int", + help="checkpoint at specified work end count") + parser.add_option("--work-cpus-checkpoint-count", action="store", type="int", + help="checkpoint and exit when active cpu count is reached") + parser.add_option("--restore-with-cpu", action="store", type="choice", + default="atomic", choices = ["atomic", "timing", + "detailed", "inorder"], + help = "cpu type for restoring from a checkpoint") + + + # CPU Switching - default switch model goes from a checkpoint + # to a timing simple CPU with caches to warm up, then to detailed CPU for + # data measurement + parser.add_option("-s", "--standard-switch", action="store_true", + help="switch from timing CPU to Detailed CPU") + parser.add_option("-w", "--warmup", action="store", type="int", + help="if -s, then this is the warmup period. else, this is ignored", + default=5000000000) + parser.add_option("-p", "--prog-interval", type="int", + help="CPU Progress Interval") + + # Fastforwarding and simpoint related materials + parser.add_option("-W", "--warmup-insts", action="store", type="int", + default=None, + help="Warmup period in total instructions (requires --standard-switch)") + parser.add_option("--bench", action="store", type="string", default=None, + help="base names for --take-checkpoint and --checkpoint-restore") + parser.add_option("-F", "--fast-forward", action="store", type="string", + default=None, + help="Number of instructions to fast forward before switching") + parser.add_option("-S", "--simpoint", action="store_true", default=False, + help="""Use workload simpoints as an instruction offset for + --checkpoint-restore or --take-checkpoint.""") + parser.add_option("--at-instruction", action="store_true", default=False, + help="""Treat value of --checkpoint-restore or --take-checkpoint as a + number of instructions.""") + +def addSEOptions(parser): + # Benchmark options + parser.add_option("-c", "--cmd", default="", + help="The binary to run in syscall emulation mode.") + parser.add_option("-o", "--options", default="", + help="""The options to pass to the binary, use " " + around the entire string""") + parser.add_option("-i", "--input", default="", + help="Read stdin from a file.") + parser.add_option("--output", default="", + help="Redirect stdout to a file.") + parser.add_option("--errout", default="", + help="Redirect stderr to a file.") + +def addFSOptions(parser): + # Simulation options + parser.add_option("--timesync", action="store_true", + help="Prevent simulated time from getting ahead of real time") + + # System options + parser.add_option("--kernel", action="store", type="string") + parser.add_option("--script", action="store", type="string") + parser.add_option("--frame-capture", action="store_true", + help="Stores changed frame buffers from the VNC server to compressed "\ + "files in the gem5 output directory") + + if buildEnv['TARGET_ISA'] == "arm": + parser.add_option("--bare-metal", action="store_true", + help="Provide the raw system without the linux specific bits") + parser.add_option("--machine-type", action="store", type="choice", + choices=ArmMachineType.map.keys(), default="RealView_PBX") + # Benchmark options + parser.add_option("--dual", action="store_true", + help="Simulate two systems attached with an ethernet link") + parser.add_option("-b", "--benchmark", action="store", type="string", + dest="benchmark", + help="Specify the benchmark to run. Available benchmarks: %s"\ + % DefinedBenchmarks) + + # Metafile options + parser.add_option("--etherdump", action="store", type="string", dest="etherdump", + help="Specify the filename to dump a pcap capture of the" \ + "ethernet traffic") + + # Disk Image Options + parser.add_option("--disk-image", action="store", type="string", default=None, + help="Path to the disk image to use.") + + # Memory Size Options + parser.add_option("--mem-size", action="store", type="string", default=None, + help="Specify the physical memory size (single memory)") diff --git a/simulators/gem5/configs/common/Simulation.py b/simulators/gem5/configs/common/Simulation.py new file mode 100644 index 00000000..58da9e96 --- /dev/null +++ b/simulators/gem5/configs/common/Simulation.py @@ -0,0 +1,407 @@ +# Copyright (c) 2006-2008 The Regents of The University of Michigan +# Copyright (c) 2010 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Lisa Hsu + +from os import getcwd +from os.path import join as joinpath + +import m5 +from m5.defines import buildEnv +from m5.objects import * +from m5.util import * +from O3_ARM_v7a import * + +addToPath('../common') + +def setCPUClass(options): + + atomic = False + if options.cpu_type == "timing": + class TmpClass(TimingSimpleCPU): pass + elif options.cpu_type == "detailed" or options.cpu_type == "arm_detailed": + if not options.caches and not options.ruby: + print "O3 CPU must be used with caches" + sys.exit(1) + if options.cpu_type == "arm_detailed": + class TmpClass(O3_ARM_v7a_3): pass + else: + class TmpClass(DerivO3CPU): pass + elif options.cpu_type == "inorder": + if not options.caches: + print "InOrder CPU must be used with caches" + sys.exit(1) + class TmpClass(InOrderCPU): pass + else: + class TmpClass(AtomicSimpleCPU): pass + atomic = True + + CPUClass = None + test_mem_mode = 'atomic' + + if not atomic: + if options.checkpoint_restore != None: + if options.restore_with_cpu != options.cpu_type: + CPUClass = TmpClass + class TmpClass(AtomicSimpleCPU): pass + else: + if options.restore_with_cpu != "atomic": + test_mem_mode = 'timing' + + elif options.fast_forward: + CPUClass = TmpClass + class TmpClass(AtomicSimpleCPU): pass + else: + test_mem_mode = 'timing' + + return (TmpClass, test_mem_mode, CPUClass) + +def setWorkCountOptions(system, options): + if options.work_item_id != None: + system.work_item_id = options.work_item_id + if options.work_begin_cpu_id_exit != None: + system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit + if options.work_end_exit_count != None: + system.work_end_exit_count = options.work_end_exit_count + if options.work_end_checkpoint_count != None: + system.work_end_ckpt_count = options.work_end_checkpoint_count + if options.work_begin_exit_count != None: + system.work_begin_exit_count = options.work_begin_exit_count + if options.work_begin_checkpoint_count != None: + system.work_begin_ckpt_count = options.work_begin_checkpoint_count + if options.work_cpus_checkpoint_count != None: + system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count + +def run(options, root, testsys, cpu_class): + if options.maxtick: + maxtick = options.maxtick + elif options.maxtime: + simtime = m5.ticks.seconds(simtime) + print "simulating for: ", simtime + maxtick = simtime + else: + maxtick = m5.MaxTick + + if options.checkpoint_dir: + cptdir = options.checkpoint_dir + elif m5.options.outdir: + cptdir = m5.options.outdir + else: + cptdir = getcwd() + + if options.fast_forward and options.checkpoint_restore != None: + fatal("Can't specify both --fast-forward and --checkpoint-restore") + + if options.standard_switch and not options.caches: + fatal("Must specify --caches when using --standard-switch") + + np = options.num_cpus + max_checkpoints = options.max_checkpoints + switch_cpus = None + + if options.prog_interval: + for i in xrange(np): + testsys.cpu[i].progress_interval = options.prog_interval + + if options.maxinsts: + for i in xrange(np): + testsys.cpu[i].max_insts_any_thread = options.maxinsts + + if cpu_class: + switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i)) + for i in xrange(np)] + + for i in xrange(np): + if options.fast_forward: + testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) + switch_cpus[i].system = testsys + switch_cpus[i].workload = testsys.cpu[i].workload + switch_cpus[i].clock = testsys.cpu[0].clock + # simulation period + if options.maxinsts: + switch_cpus[i].max_insts_any_thread = options.maxinsts + # Add checker cpu if selected + if options.checker: + switch_cpus[i].addCheckerCpu() + + testsys.switch_cpus = switch_cpus + switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)] + + if options.standard_switch: + if not options.caches: + # O3 CPU must have a cache to work. + print "O3 CPU must be used with caches" + sys.exit(1) + + switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i)) + for i in xrange(np)] + switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i)) + for i in xrange(np)] + + for i in xrange(np): + switch_cpus[i].system = testsys + switch_cpus_1[i].system = testsys + switch_cpus[i].workload = testsys.cpu[i].workload + switch_cpus_1[i].workload = testsys.cpu[i].workload + switch_cpus[i].clock = testsys.cpu[0].clock + switch_cpus_1[i].clock = testsys.cpu[0].clock + + # if restoring, make atomic cpu simulate only a few instructions + if options.checkpoint_restore != None: + testsys.cpu[i].max_insts_any_thread = 1 + # Fast forward to specified location if we are not restoring + elif options.fast_forward: + testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) + # Fast forward to a simpoint (warning: time consuming) + elif options.simpoint: + if testsys.cpu[i].workload[0].simpoint == 0: + fatal('simpoint not found') + testsys.cpu[i].max_insts_any_thread = \ + testsys.cpu[i].workload[0].simpoint + # No distance specified, just switch + else: + testsys.cpu[i].max_insts_any_thread = 1 + + # warmup period + if options.warmup_insts: + switch_cpus[i].max_insts_any_thread = options.warmup_insts + + # simulation period + if options.maxinsts: + switch_cpus_1[i].max_insts_any_thread = options.maxinsts + + # attach the checker cpu if selected + if options.checker: + switch_cpus[i].addCheckerCpu() + switch_cpus_1[i].addCheckerCpu() + + testsys.switch_cpus = switch_cpus + testsys.switch_cpus_1 = switch_cpus_1 + switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)] + switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)] + + # set the checkpoint in the cpu before m5.instantiate is called + if options.take_checkpoints != None and \ + (options.simpoint or options.at_instruction): + offset = int(options.take_checkpoints) + # Set an instruction break point + if options.simpoint: + for i in xrange(np): + if testsys.cpu[i].workload[0].simpoint == 0: + fatal('no simpoint for testsys.cpu[%d].workload[0]', i) + checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset + testsys.cpu[i].max_insts_any_thread = checkpoint_inst + # used for output below + options.take_checkpoints = checkpoint_inst + else: + options.take_checkpoints = offset + # Set all test cpus with the right number of instructions + # for the upcoming simulation + for i in xrange(np): + testsys.cpu[i].max_insts_any_thread = offset + + checkpoint_dir = None + if options.checkpoint_restore != None: + from os.path import isdir, exists + from os import listdir + import re + + if not isdir(cptdir): + fatal("checkpoint dir %s does not exist!", cptdir) + + if options.at_instruction or options.simpoint: + inst = options.checkpoint_restore + if options.simpoint: + # assume workload 0 has the simpoint + if testsys.cpu[0].workload[0].simpoint == 0: + fatal('Unable to find simpoint') + inst += int(testsys.cpu[0].workload[0].simpoint) + + checkpoint_dir = joinpath(cptdir, + "cpt.%s.%s" % (options.bench, inst)) + if not exists(checkpoint_dir): + fatal("Unable to find checkpoint directory %s", checkpoint_dir) + else: + dirs = listdir(cptdir) + expr = re.compile('cpt\.([0-9]*)') + cpts = [] + for dir in dirs: + match = expr.match(dir) + if match: + cpts.append(match.group(1)) + + cpts.sort(lambda a,b: cmp(long(a), long(b))) + + cpt_num = options.checkpoint_restore + + if cpt_num > len(cpts): + fatal('Checkpoint %d not found', cpt_num) + + ## Adjust max tick based on our starting tick + maxtick = maxtick - int(cpts[cpt_num - 1]) + checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]) + + m5.instantiate(checkpoint_dir) + + if options.standard_switch or cpu_class: + if options.standard_switch: + print "Switch at instruction count:%s" % \ + str(testsys.cpu[0].max_insts_any_thread) + exit_event = m5.simulate() + elif cpu_class and options.fast_forward: + print "Switch at instruction count:%s" % \ + str(testsys.cpu[0].max_insts_any_thread) + exit_event = m5.simulate() + else: + print "Switch at curTick count:%s" % str(10000) + exit_event = m5.simulate(10000) + print "Switched CPUS @ tick %s" % (m5.curTick()) + + # when you change to Timing (or Atomic), you halt the system + # given as argument. When you are finished with the system + # changes (including switchCpus), you must resume the system + # manually. You DON'T need to resume after just switching + # CPUs if you haven't changed anything on the system level. + + m5.changeToTiming(testsys) + m5.switchCpus(switch_cpu_list) + m5.resume(testsys) + + if options.standard_switch: + print "Switch at instruction count:%d" % \ + (testsys.switch_cpus[0].max_insts_any_thread) + + #warmup instruction count may have already been set + if options.warmup_insts: + exit_event = m5.simulate() + else: + exit_event = m5.simulate(options.warmup) + print "Switching CPUS @ tick %s" % (m5.curTick()) + print "Simulation ends instruction count:%d" % \ + (testsys.switch_cpus_1[0].max_insts_any_thread) + m5.drain(testsys) + m5.switchCpus(switch_cpu_list1) + m5.resume(testsys) + + num_checkpoints = 0 + exit_cause = '' + + # If we're taking and restoring checkpoints, use checkpoint_dir + # option only for finding the checkpoints to restore from. This + # lets us test checkpointing by restoring from one set of + # checkpoints, generating a second set, and then comparing them. + if options.take_checkpoints and options.checkpoint_restore: + if m5.options.outdir: + cptdir = m5.options.outdir + else: + cptdir = getcwd() + + # Checkpoints being taken via the command line at and at + # subsequent periods of . Checkpoint instructions + # received from the benchmark running are ignored and skipped in + # favor of command line checkpoint instructions. + if options.take_checkpoints != None : + if options.at_instruction or options.simpoint: + checkpoint_inst = int(options.take_checkpoints) + + # maintain correct offset if we restored from some instruction + if options.checkpoint_restore != None: + checkpoint_inst += options.checkpoint_restore + + print "Creating checkpoint at inst:%d" % (checkpoint_inst) + exit_event = m5.simulate() + print "exit cause = %s" % (exit_event.getCause()) + + # skip checkpoint instructions should they exist + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate() + + if exit_event.getCause() == \ + "a thread reached the max instruction count": + m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \ + (options.bench, checkpoint_inst))) + print "Checkpoint written." + num_checkpoints += 1 + + if exit_event.getCause() == "user interrupt received": + exit_cause = exit_event.getCause(); + else: + when, period = options.take_checkpoints.split(",", 1) + when = int(when) + period = int(period) + + exit_event = m5.simulate(when) + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(when - m5.curTick()) + + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + num_checkpoints += 1 + + sim_ticks = when + exit_cause = "maximum %d checkpoints dropped" % max_checkpoints + while num_checkpoints < max_checkpoints and \ + exit_event.getCause() == "simulate() limit reached": + if (sim_ticks + period) > maxtick: + exit_event = m5.simulate(maxtick - sim_ticks) + exit_cause = exit_event.getCause() + break + else: + exit_event = m5.simulate(period) + sim_ticks += period + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(sim_ticks - m5.curTick()) + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + num_checkpoints += 1 + + if exit_event.getCause() != "simulate() limit reached": + exit_cause = exit_event.getCause(); + + else: # no checkpoints being taken via this script + if options.fast_forward: + m5.stats.reset() + print "**** REAL SIMULATION ****" + exit_event = m5.simulate(maxtick) + + while exit_event.getCause() == "checkpoint": + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + num_checkpoints += 1 + if num_checkpoints == max_checkpoints: + exit_cause = "maximum %d checkpoints dropped" % max_checkpoints + break + + exit_event = m5.simulate(maxtick - m5.curTick()) + exit_cause = exit_event.getCause() + + if exit_cause == '': + exit_cause = exit_event.getCause() + print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause) + + if options.checkpoint_at_end: + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + diff --git a/simulators/gem5/configs/common/SysPaths.py b/simulators/gem5/configs/common/SysPaths.py new file mode 100644 index 00000000..c61c9962 --- /dev/null +++ b/simulators/gem5/configs/common/SysPaths.py @@ -0,0 +1,71 @@ +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +import os, sys +from os.path import isdir, join as joinpath +from os import environ as env + +config_path = os.path.dirname(os.path.abspath(__file__)) +config_root = os.path.dirname(config_path) + +def disk(file): + system() + return joinpath(disk.dir, file) + +def binary(file): + system() + return joinpath(binary.dir, file) + +def script(file): + system() + return joinpath(script.dir, file) + +def system(): + if not system.dir: + try: + path = env['M5_PATH'].split(':') + except KeyError: + path = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ] + + for system.dir in path: + if os.path.isdir(system.dir): + break + else: + raise ImportError, "Can't find a path to system files." + + if not binary.dir: + binary.dir = joinpath(system.dir, 'binaries') + if not disk.dir: + disk.dir = joinpath(system.dir, 'disks') + if not script.dir: + script.dir = joinpath(config_root, 'boot') + +system.dir = None +binary.dir = None +disk.dir = None +script.dir = None diff --git a/simulators/gem5/configs/common/cpu2000.py b/simulators/gem5/configs/common/cpu2000.py new file mode 100644 index 00000000..44339923 --- /dev/null +++ b/simulators/gem5/configs/common/cpu2000.py @@ -0,0 +1,754 @@ +# Copyright (c) 2006-2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import os +import sys +from os.path import basename, exists, join as joinpath, normpath +from os.path import isdir, isfile, islink + +spec_dist = os.environ.get('M5_CPU2000', '/dist/m5/cpu2000') + +def copyfiles(srcdir, dstdir): + from filecmp import cmp as filecmp + from shutil import copyfile + + srcdir = normpath(srcdir) + dstdir = normpath(dstdir) + + if not isdir(dstdir): + os.mkdir(dstdir) + + for root, dirs, files in os.walk(srcdir): + root = normpath(root) + prefix = os.path.commonprefix([root, srcdir]) + + root = root[len(prefix):] + if root.startswith('/'): + root = root[1:] + + for entry in dirs: + newdir = joinpath(dstdir, root, entry) + if not isdir(newdir): + os.mkdir(newdir) + + for entry in files: + dest = normpath(joinpath(dstdir, root, entry)) + src = normpath(joinpath(srcdir, root, entry)) + if not isfile(dest) or not filecmp(src, dest): + copyfile(src, dest) + + # some of the spec benchmarks expect to be run from one directory up. + # just create some symlinks that solve the problem + inlink = joinpath(dstdir, 'input') + outlink = joinpath(dstdir, 'output') + if not exists(inlink): + os.symlink('.', inlink) + if not exists(outlink): + os.symlink('.', outlink) + +class Benchmark(object): + def __init__(self, isa, os, input_set): + if not hasattr(self.__class__, 'name'): + self.name = self.__class__.__name__ + + if not hasattr(self.__class__, 'binary'): + self.binary = self.name + + if not hasattr(self.__class__, 'args'): + self.args = [] + + if not hasattr(self.__class__, 'output'): + self.output = '%s.out' % self.name + + if not hasattr(self.__class__, 'simpoint'): + self.simpoint = None + + try: + func = getattr(self.__class__, input_set) + except AttributeError: + raise AttributeError, \ + 'The benchmark %s does not have the %s input set' % \ + (self.name, input_set) + + executable = joinpath(spec_dist, 'binaries', isa, os, self.binary) + if not isfile(executable): + raise AttributeError, '%s not found' % executable + self.executable = executable + + # root of tree for input & output data files + data_dir = joinpath(spec_dist, 'data', self.name) + # optional subtree with files shared across input sets + all_dir = joinpath(data_dir, 'all') + # dirs for input & output files for this input set + inputs_dir = joinpath(data_dir, input_set, 'input') + outputs_dir = joinpath(data_dir, input_set, 'output') + # keep around which input set was specified + self.input_set = input_set + + if not isdir(inputs_dir): + raise AttributeError, '%s not found' % inputs_dir + + self.inputs_dir = [ inputs_dir ] + if isdir(all_dir): + self.inputs_dir += [ joinpath(all_dir, 'input') ] + if isdir(outputs_dir): + self.outputs_dir = outputs_dir + + if not hasattr(self.__class__, 'stdin'): + self.stdin = joinpath(inputs_dir, '%s.in' % self.name) + if not isfile(self.stdin): + self.stdin = None + + if not hasattr(self.__class__, 'stdout'): + self.stdout = joinpath(outputs_dir, '%s.out' % self.name) + if not isfile(self.stdout): + self.stdout = None + + func(self, isa, os) + + def makeLiveProcessArgs(self, **kwargs): + # set up default args for LiveProcess object + process_args = {} + process_args['cmd'] = [ self.name ] + self.args + process_args['executable'] = self.executable + if self.stdin: + process_args['input'] = self.stdin + if self.stdout: + process_args['output'] = self.stdout + if self.simpoint: + process_args['simpoint'] = self.simpoint + # explicit keywords override defaults + process_args.update(kwargs) + + return process_args + + def makeLiveProcess(self, **kwargs): + process_args = self.makeLiveProcessArgs(**kwargs) + + # figure out working directory: use m5's outdir unless + # overridden by LiveProcess's cwd param + cwd = process_args.get('cwd') + + if not cwd: + from m5 import options + cwd = options.outdir + process_args['cwd'] = cwd + if not isdir(cwd): + os.makedirs(cwd) + # copy input files to working directory + for d in self.inputs_dir: + copyfiles(d, cwd) + # generate LiveProcess object + from m5.objects import LiveProcess + return LiveProcess(**process_args) + + def __str__(self): + return self.name + +class DefaultBenchmark(Benchmark): + def ref(self, isa, os): pass + def test(self, isa, os): pass + def train(self, isa, os): pass + +class MinneDefaultBenchmark(DefaultBenchmark): + def smred(self, isa, os): pass + def mdred(self, isa, os): pass + def lgred(self, isa, os): pass + +class ammp(MinneDefaultBenchmark): + name = 'ammp' + number = 188 + lang = 'C' + simpoint = 108*100E6 + +class applu(MinneDefaultBenchmark): + name = 'applu' + number = 173 + lang = 'F77' + simpoint = 2179*100E6 + +class apsi(MinneDefaultBenchmark): + name = 'apsi' + number = 301 + lang = 'F77' + simpoint = 3408*100E6 + +class art(DefaultBenchmark): + name = 'art' + number = 179 + lang = 'C' + + def test(self, isa, os): + self.args = [ '-scanfile', 'c756hel.in', + '-trainfile1', 'a10.img', + '-stride', '2', + '-startx', '134', + '-starty', '220', + '-endx', '139', + '-endy', '225', + '-objects', '1' ] + self.output = 'test.out' + + def train(self, isa, os): + self.args = [ '-scanfile', 'c756hel.in', + '-trainfile1', 'a10.img', + '-stride', '2', + '-startx', '134', + '-starty', '220', + '-endx', '184', + '-endy', '240', + '-objects', '3' ] + self.output = 'train.out' + + def lgred(self, isa, os): + self.args = ['-scanfile', 'c756hel.in', + '-trainfile1', 'a10.img', + '-stride', '5', + '-startx', '134', + '-starty', '220', + '-endx', '184', + '-endy', '240', + '-objects', '1' ] + self.output = 'lgred.out' + + +class art110(art): + def ref(self, isa, os): + self.args = [ '-scanfile', 'c756hel.in', + '-trainfile1', 'a10.img', + '-trainfile2', 'hc.img', + '-stride', '2', + '-startx', '110', + '-starty', '200', + '-endx', '160', + '-endy', '240', + '-objects', '10' ] + self.output = 'ref.1.out' + self.simpoint = 340*100E6 + +class art470(art): + def ref(self, isa, os): + self.args = [ '-scanfile', 'c756hel.in', + '-trainfile1', 'a10.img', + '-trainfile2', 'hc.img', + '-stride', '2', + '-startx', '470', + '-starty', '140', + '-endx', '520', + '-endy', '180', + '-objects', '10' ] + self.output = 'ref.2.out' + self.simpoint = 365*100E6 + +class equake(DefaultBenchmark): + name = 'equake' + number = 183 + lang = 'C' + simpoint = 812*100E6 + + def lgred(self, isa, os): pass + +class facerec(MinneDefaultBenchmark): + name = 'facerec' + number = 187 + lang = 'F' + simpoint = 375*100E6 + +class fma3d(MinneDefaultBenchmark): + name = 'fma3d' + number = 191 + lang = 'F' + simpoint = 2541*100E6 + +class galgel(MinneDefaultBenchmark): + name = 'galgel' + number = 178 + lang = 'F' + simpoint = 2491*100E6 + +class lucas(MinneDefaultBenchmark): + name = 'lucas' + number = 189 + lang = 'F' + simpoint = 545*100E6 + +class mesa(Benchmark): + name = 'mesa' + number = 177 + lang = 'C' + stdin = None + + def __set_args(self, frames): + self.args = [ '-frames', frames, '-meshfile', '%s.in' % self.name, + '-ppmfile', '%s.ppm' % self.name ] + + def test(self, isa, os): + self.__set_args('10') + + def train(self, isa, os): + self.__set_args('500') + + def ref(self, isa, os): + self.__set_args('1000') + self.simpoint = 1135*100E6 + + def lgred(self, isa, os): + self.__set_args('1') + +class mgrid(MinneDefaultBenchmark): + name = 'mgrid' + number = 172 + lang = 'F77' + simpoint = 3292*100E6 + +class sixtrack(DefaultBenchmark): + name = 'sixtrack' + number = 200 + lang = 'F77' + simpoint = 3043*100E6 + + def lgred(self, isa, os): pass + +class swim(MinneDefaultBenchmark): + name = 'swim' + number = 171 + lang = 'F77' + simpoint = 2079*100E6 + +class wupwise(DefaultBenchmark): + name = 'wupwise' + number = 168 + lang = 'F77' + simpoint = 3237*100E6 + + def lgred(self, isa, os): pass + +class bzip2(DefaultBenchmark): + name = 'bzip2' + number = 256 + lang = 'C' + + def test(self, isa, os): + self.args = [ 'input.random' ] + + def train(self, isa, os): + self.args = [ 'input.compressed' ] + +class bzip2_source(bzip2): + def ref(self, isa, os): + self.simpoint = 977*100E6 + self.args = [ 'input.source', '58' ] + + def lgred(self, isa, os): + self.args = [ 'input.source', '1' ] + +class bzip2_graphic(bzip2): + def ref(self, isa, os): + self.simpoint = 718*100E6 + self.args = [ 'input.graphic', '58' ] + + def lgred(self, isa, os): + self.args = [ 'input.graphic', '1' ] + +class bzip2_program(bzip2): + def ref(self, isa, os): + self.simpoint = 458*100E6 + self.args = [ 'input.program', '58' ] + + def lgred(self, isa, os): + self.args = [ 'input.program', '1' ] + +class crafty(MinneDefaultBenchmark): + name = 'crafty' + number = 186 + lang = 'C' + simpoint = 774*100E6 + +class eon(MinneDefaultBenchmark): + name = 'eon' + number = 252 + lang = 'CXX' + stdin = None + +class eon_kajiya(eon): + args = [ 'chair.control.kajiya', 'chair.camera', 'chair.surfaces', + 'chair.kajiya.ppm', 'ppm', 'pixels_out.kajiya'] + output = 'kajiya_log.out' + + +class eon_cook(eon): + args = [ 'chair.control.cook', 'chair.camera', 'chair.surfaces', + 'chair.cook.ppm', 'ppm', 'pixels_out.cook' ] + output = 'cook_log.out' + +class eon_rushmeier(eon): + args = [ 'chair.control.rushmeier', 'chair.camera', 'chair.surfaces', + 'chair.rushmeier.ppm', 'ppm', 'pixels_out.rushmeier' ] + output = 'rushmeier_log.out' + simpoint = 403*100E6 + +class gap(DefaultBenchmark): + name = 'gap' + number = 254 + lang = 'C' + + def __set_args(self, size): + self.args = [ '-l', './', '-q', '-m', size ] + + def test(self, isa, os): + self.__set_args('64M') + + def train(self, isa, os): + self.__set_args('128M') + + def ref(self, isa, os): + self.__set_args('192M') + self.simpoint = 674*100E6 + + def lgred(self, isa, os): + self.__set_args('64M') + + def mdred(self, isa, os): + self.__set_args('64M') + + def smred(self, isa, os): + self.__set_args('64M') + +class gcc(DefaultBenchmark): + name = 'gcc' + number = 176 + lang = 'C' + + def test(self, isa, os): + self.args = [ 'cccp.i', '-o', 'cccp.s' ] + + def train(self, isa, os): + self.args = [ 'cp-decl.i', '-o', 'cp-decl.s' ] + + def smred(self, isa, os): + self.args = [ 'c-iterate.i', '-o', 'c-iterate.s' ] + + def mdred(self, isa, os): + self.args = [ 'rdlanal.i', '-o', 'rdlanal.s' ] + + def lgred(self, isa, os): + self.args = [ 'cp-decl.i', '-o', 'cp-decl.s' ] + +class gcc_166(gcc): + def ref(self, isa, os): + self.simpoint = 389*100E6 + self.args = [ '166.i', '-o', '166.s' ] + +class gcc_200(gcc): + def ref(self, isa, os): + self.simpoint = 736*100E6 + self.args = [ '200.i', '-o', '200.s' ] + +class gcc_expr(gcc): + def ref(self, isa, os): + self.simpoint = 36*100E6 + self.args = [ 'expr.i', '-o', 'expr.s' ] + +class gcc_integrate(gcc): + def ref(self, isa, os): + self.simpoint = 4*100E6 + self.args = [ 'integrate.i', '-o', 'integrate.s' ] + +class gcc_scilab(gcc): + def ref(self, isa, os): + self.simpoint = 207*100E6 + self.args = [ 'scilab.i', '-o', 'scilab.s' ] + +class gzip(DefaultBenchmark): + name = 'gzip' + number = 164 + lang = 'C' + + def test(self, isa, os): + self.args = [ 'input.compressed', '2' ] + + def train(self, isa, os): + self.args = [ 'input.combined', '32' ] + +class gzip_source(gzip): + def ref(self, isa, os): + self.simpoint = 334*100E6 + self.args = [ 'input.source', '1' ] + def smred(self, isa, os): + self.args = [ 'input.source', '1' ] + def mdred(self, isa, os): + self.args = [ 'input.source', '1' ] + def lgred(self, isa, os): + self.args = [ 'input.source', '1' ] + +class gzip_log(gzip): + def ref(self, isa, os): + self.simpoint = 265*100E6 + self.args = [ 'input.log', '60' ] + def smred(self, isa, os): + self.args = [ 'input.log', '1' ] + def mdred(self, isa, os): + self.args = [ 'input.log', '1' ] + def lgred(self, isa, os): + self.args = [ 'input.log', '1' ] + +class gzip_graphic(gzip): + def ref(self, isa, os): + self.simpoint = 653*100E6 + self.args = [ 'input.graphic', '60' ] + def smred(self, isa, os): + self.args = [ 'input.graphic', '1' ] + def mdred(self, isa, os): + self.args = [ 'input.graphic', '1' ] + def lgred(self, isa, os): + self.args = [ 'input.graphic', '1' ] + +class gzip_random(gzip): + def ref(self, isa, os): + self.simpoint = 623*100E6 + self.args = [ 'input.random', '60' ] + def smred(self, isa, os): + self.args = [ 'input.random', '1' ] + def mdred(self, isa, os): + self.args = [ 'input.random', '1' ] + def lgred(self, isa, os): + self.args = [ 'input.random', '1' ] + +class gzip_program(gzip): + def ref(self, isa, os): + self.simpoint = 1189*100E6 + self.args = [ 'input.program', '60' ] + def smred(self, isa, os): + self.args = [ 'input.program', '1' ] + def mdred(self, isa, os): + self.args = [ 'input.program', '1' ] + def lgred(self, isa, os): + self.args = [ 'input.program', '1' ] + +class mcf(MinneDefaultBenchmark): + name = 'mcf' + number = 181 + lang = 'C' + args = [ 'mcf.in' ] + simpoint = 553*100E6 + +class parser(MinneDefaultBenchmark): + name = 'parser' + number = 197 + lang = 'C' + args = [ '2.1.dict', '-batch' ] + simpoint = 1146*100E6 + +class perlbmk(DefaultBenchmark): + name = 'perlbmk' + number = 253 + lang = 'C' + + def test(self, isa, os): + self.args = [ '-I.', '-I', 'lib', 'test.pl' ] + self.stdin = 'test.in' + +class perlbmk_diffmail(perlbmk): + def ref(self, isa, os): + self.simpoint = 141*100E6 + self.args = [ '-I', 'lib', 'diffmail.pl', '2', '550', '15', '24', + '23', '100' ] + + def train(self, isa, os): + self.args = [ '-I', 'lib', 'diffmail.pl', '2', '350', '15', '24', + '23', '150' ] + +class perlbmk_scrabbl(perlbmk): + def train(self, isa, os): + self.args = [ '-I.', '-I', 'lib', 'scrabbl.pl' ] + self.stdin = 'scrabbl.in' + +class perlbmk_makerand(perlbmk): + def ref(self, isa, os): + self.simpoint = 11*100E6 + self.args = [ '-I', 'lib', 'makerand.pl' ] + + def lgred(self, isa, os): + self.args = [ '-I.', '-I', 'lib', 'lgred.makerand.pl' ] + + def mdred(self, isa, os): + self.args = [ '-I.', '-I', 'lib', 'mdred.makerand.pl' ] + + def smred(self, isa, os): + self.args = [ '-I.', '-I', 'lib', 'smred.makerand.pl' ] + +class perlbmk_perfect(perlbmk): + def ref(self, isa, os): + self.simpoint = 5*100E6 + self.args = [ '-I', 'lib', 'perfect.pl', 'b', '3', 'm', '4' ] + + def train(self, isa, os): + self.args = [ '-I', 'lib', 'perfect.pl', 'b', '3' ] + +class perlbmk_splitmail1(perlbmk): + def ref(self, isa, os): + self.simpoint = 405*100E6 + self.args = [ '-I', 'lib', 'splitmail.pl', '850', '5', '19', + '18', '1500' ] + +class perlbmk_splitmail2(perlbmk): + def ref(self, isa, os): + self.args = [ '-I', 'lib', 'splitmail.pl', '704', '12', '26', + '16', '836' ] + +class perlbmk_splitmail3(perlbmk): + def ref(self, isa, os): + self.args = [ '-I', 'lib', 'splitmail.pl', '535', '13', '25', + '24', '1091' ] + +class perlbmk_splitmail4(perlbmk): + def ref(self, isa, os): + self.args = [ '-I', 'lib', 'splitmail.pl', '957', '12', '23', + '26', '1014' ] + +class twolf(Benchmark): + name = 'twolf' + number = 300 + lang = 'C' + stdin = None + + def test(self, isa, os): + self.args = [ 'test' ] + + def train(self, isa, os): + self.args = [ 'train' ] + + def ref(self, isa, os): + self.simpoint = 1066*100E6 + self.args = [ 'ref' ] + + def smred(self, isa, os): + self.args = [ 'smred' ] + + def mdred(self, isa, os): + self.args = [ 'mdred' ] + + def lgred(self, isa, os): + self.args = [ 'lgred' ] + +class vortex(Benchmark): + name = 'vortex' + number = 255 + lang = 'C' + stdin = None + + def __init__(self, isa, os, input_set): + if (isa == 'alpha' or isa == 'arm'): + self.endian = 'lendian' + elif (isa == 'sparc' or isa == 'sparc32'): + self.endian = 'bendian' + else: + raise AttributeError, "unknown ISA %s" % isa + + super(vortex, self).__init__(isa, os, input_set) + + def test(self, isa, os): + self.args = [ '%s.raw' % self.endian ] + self.output = 'vortex.out' + + def train(self, isa, os): + self.args = [ '%s.raw' % self.endian ] + self.output = 'vortex.out' + + def smred(self, isa, os): + self.args = [ '%s.raw' % self.endian ] + self.output = 'vortex.out' + + def mdred(self, isa, os): + self.args = [ '%s.raw' % self.endian ] + self.output = 'vortex.out' + + def lgred(self, isa, os): + self.args = [ '%s.raw' % self.endian ] + self.output = 'vortex.out' + +class vortex1(vortex): + def ref(self, isa, os): + self.args = [ '%s1.raw' % self.endian ] + self.output = 'vortex1.out' + self.simpoint = 271*100E6 + + +class vortex2(vortex): + def ref(self, isa, os): + self.simpoint = 1024*100E6 + self.args = [ '%s2.raw' % self.endian ] + self.output = 'vortex2.out' + +class vortex3(vortex): + def ref(self, isa, os): + self.simpoint = 564*100E6 + self.args = [ '%s3.raw' % self.endian ] + self.output = 'vortex3.out' + +class vpr(MinneDefaultBenchmark): + name = 'vpr' + number = 175 + lang = 'C' + +# not sure about vpr minnespec place.in +class vpr_place(vpr): + args = [ 'net.in', 'arch.in', 'place.out', 'dum.out', '-nodisp', + '-place_only', '-init_t', '5', '-exit_t', '0.005', + '-alpha_t', '0.9412', '-inner_num', '2' ] + output = 'place_log.out' + +class vpr_route(vpr): + simpoint = 476*100E6 + args = [ 'net.in', 'arch.in', 'place.in', 'route.out', '-nodisp', + '-route_only', '-route_chan_width', '15', + '-pres_fac_mult', '2', '-acc_fac', '1', + '-first_iter_pres_fac', '4', '-initial_pres_fac', '8' ] + output = 'route_log.out' + +all = [ ammp, applu, apsi, art, art110, art470, equake, facerec, fma3d, galgel, + lucas, mesa, mgrid, sixtrack, swim, wupwise, bzip2_source, + bzip2_graphic, bzip2_program, crafty, eon_kajiya, eon_cook, + eon_rushmeier, gap, gcc_166, gcc_200, gcc_expr, gcc_integrate, + gcc_scilab, gzip_source, gzip_log, gzip_graphic, gzip_random, + gzip_program, mcf, parser, perlbmk_diffmail, perlbmk_makerand, + perlbmk_perfect, perlbmk_splitmail1, perlbmk_splitmail2, + perlbmk_splitmail3, perlbmk_splitmail4, twolf, vortex1, vortex2, + vortex3, vpr_place, vpr_route ] + +__all__ = [ x.__name__ for x in all ] + +if __name__ == '__main__': + from pprint import pprint + for bench in all: + for input_set in 'ref', 'test', 'train': + print 'class: %s' % bench.__name__ + x = bench('alpha', 'tru64', input_set) + print '%s: %s' % (x, input_set) + pprint(x.makeLiveProcessArgs()) + print diff --git a/simulators/gem5/configs/example/fs.py b/simulators/gem5/configs/example/fs.py new file mode 100644 index 00000000..a6d4869f --- /dev/null +++ b/simulators/gem5/configs/example/fs.py @@ -0,0 +1,185 @@ +# Copyright (c) 2010-2012 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +import optparse +import sys + +import m5 +from m5.defines import buildEnv +from m5.objects import * +from m5.util import addToPath, fatal + +addToPath('../common') + +from FSConfig import * +from SysPaths import * +from Benchmarks import * +import Simulation +import CacheConfig +from Caches import * +import Options + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) +Options.addFSOptions(parser) + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +# driver system CPU is always simple... note this is an assignment of +# a class, not an instance. +DriveCPUClass = AtomicSimpleCPU +drive_mem_mode = 'atomic' + +# system under test can be any CPU +(TestCPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options) + +TestCPUClass.clock = '2GHz' +DriveCPUClass.clock = '2GHz' + +if options.benchmark: + try: + bm = Benchmarks[options.benchmark] + except KeyError: + print "Error benchmark %s has not been defined." % options.benchmark + print "Valid benchmarks are: %s" % DefinedBenchmarks + sys.exit(1) +else: + if options.dual: + bm = [SysConfig(disk=options.disk_image, mem=options.mem_size), SysConfig(disk=options.disk_image, mem=options.mem_size)] + else: + bm = [SysConfig(disk=options.disk_image, mem=options.mem_size)] + +np = options.num_cpus + +if buildEnv['TARGET_ISA'] == "alpha": + test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0]) +elif buildEnv['TARGET_ISA'] == "mips": + test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0]) +elif buildEnv['TARGET_ISA'] == "sparc": + test_sys = makeSparcSystem(test_mem_mode, bm[0]) +elif buildEnv['TARGET_ISA'] == "x86": + test_sys = makeLinuxX86System(test_mem_mode, options.num_cpus, bm[0]) +elif buildEnv['TARGET_ISA'] == "arm": + test_sys = makeArmSystem(test_mem_mode, + options.machine_type, bm[0], + bare_metal=options.bare_metal) +else: + fatal("Incapable of building %s full system!", buildEnv['TARGET_ISA']) + +if options.kernel is not None: + test_sys.kernel = binary(options.kernel) + +if options.script is not None: + test_sys.readfile = options.script + +test_sys.init_param = options.init_param + +test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)] + +if bm[0]: + mem_size = bm[0].mem() +else: + mem_size = SysConfig().mem() +if options.caches or options.l2cache: + test_sys.iocache = IOCache(addr_ranges=[test_sys.physmem.range]) + test_sys.iocache.cpu_side = test_sys.iobus.master + test_sys.iocache.mem_side = test_sys.membus.slave +else: + test_sys.iobridge = Bridge(delay='50ns', nack_delay='4ns', + ranges = [test_sys.physmem.range]) + test_sys.iobridge.slave = test_sys.iobus.master + test_sys.iobridge.master = test_sys.membus.slave + +# Sanity check +if options.fastmem and (options.caches or options.l2cache): + fatal("You cannot use fastmem in combination with caches!") + +for i in xrange(np): + if options.fastmem: + test_sys.cpu[i].fastmem = True + if options.checker: + test_sys.cpu[i].addCheckerCpu() + +CacheConfig.config_cache(options, test_sys) + +if len(bm) == 2: + if buildEnv['TARGET_ISA'] == 'alpha': + drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1]) + elif buildEnv['TARGET_ISA'] == 'mips': + drive_sys = makeLinuxMipsSystem(drive_mem_mode, bm[1]) + elif buildEnv['TARGET_ISA'] == 'sparc': + drive_sys = makeSparcSystem(drive_mem_mode, bm[1]) + elif buildEnv['TARGET_ISA'] == 'x86': + drive_sys = makeX86System(drive_mem_mode, np, bm[1]) + elif buildEnv['TARGET_ISA'] == 'arm': + drive_sys = makeArmSystem(drive_mem_mode, options.machine_type, bm[1]) + + drive_sys.cpu = DriveCPUClass(cpu_id=0) + drive_sys.cpu.createInterruptController() + drive_sys.cpu.connectAllPorts(drive_sys.membus) + if options.fastmem: + drive_sys.cpu.fastmem = True + if options.kernel is not None: + drive_sys.kernel = binary(options.kernel) + drive_sys.iobridge = Bridge(delay='50ns', nack_delay='4ns', + ranges = [drive_sys.physmem.range]) + drive_sys.iobridge.slave = drive_sys.iobus.master + drive_sys.iobridge.master = drive_sys.membus.slave + + drive_sys.init_param = options.init_param + root = makeDualRoot(True, test_sys, drive_sys, options.etherdump) +elif len(bm) == 1: + root = Root(full_system=True, system=test_sys) +else: + print "Error I don't know how to create more than 2 systems." + sys.exit(1) + +if options.timesync: + root.time_sync_enable = True + +if options.frame_capture: + VncServer.frame_capture = True + +Simulation.setWorkCountOptions(test_sys, options) +Simulation.run(options, root, test_sys, FutureClass) diff --git a/simulators/gem5/configs/example/memtest.py b/simulators/gem5/configs/example/memtest.py new file mode 100644 index 00000000..59037892 --- /dev/null +++ b/simulators/gem5/configs/example/memtest.py @@ -0,0 +1,199 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski + +import optparse +import sys + +import m5 +from m5.objects import * + +parser = optparse.OptionParser() + +parser.add_option("-a", "--atomic", action="store_true", + help="Use atomic (non-timing) mode") +parser.add_option("-b", "--blocking", action="store_true", + help="Use blocking caches") +parser.add_option("-l", "--maxloads", metavar="N", default=0, + help="Stop after N loads") +parser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick, + metavar="T", + help="Stop after T ticks") + +# +# The "tree" specification is a colon-separated list of one or more +# integers. The first integer is the number of caches/testers +# connected directly to main memory. The last integer in the list is +# the number of testers associated with the uppermost level of memory +# (L1 cache, if there are caches, or main memory if no caches). Thus +# if there is only one integer, there are no caches, and the integer +# specifies the number of testers connected directly to main memory. +# The other integers (if any) specify the number of caches at each +# level of the hierarchy between. +# +# Examples: +# +# "2:1" Two caches connected to memory with a single tester behind each +# (single-level hierarchy, two testers total) +# +# "2:2:1" Two-level hierarchy, 2 L1s behind each of 2 L2s, 4 testers total +# +parser.add_option("-t", "--treespec", type="string", default="8:1", + help="Colon-separated multilevel tree specification, " + "see script comments for details " + "[default: %default]") + +parser.add_option("--force-bus", action="store_true", + help="Use bus between levels even with single cache") + +parser.add_option("-f", "--functional", type="int", default=0, + metavar="PCT", + help="Target percentage of functional accesses " + "[default: %default]") +parser.add_option("-u", "--uncacheable", type="int", default=0, + metavar="PCT", + help="Target percentage of uncacheable accesses " + "[default: %default]") + +parser.add_option("--progress", type="int", default=1000, + metavar="NLOADS", + help="Progress message interval " + "[default: %default]") + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +block_size = 64 + +try: + treespec = [int(x) for x in options.treespec.split(':')] + numtesters = reduce(lambda x,y: x*y, treespec) +except: + print "Error parsing treespec option" + sys.exit(1) + +if numtesters > block_size: + print "Error: Number of testers limited to %s because of false sharing" \ + % (block_size) + sys.exit(1) + +if len(treespec) < 1: + print "Error parsing treespec" + sys.exit(1) + +# define prototype L1 cache +proto_l1 = BaseCache(size = '32kB', assoc = 4, block_size = block_size, + latency = '1ns', tgts_per_mshr = 8) + +if options.blocking: + proto_l1.mshrs = 1 +else: + proto_l1.mshrs = 4 + +# build a list of prototypes, one for each level of treespec, starting +# at the end (last entry is tester objects) +prototypes = [ MemTest(atomic=options.atomic, max_loads=options.maxloads, + percent_functional=options.functional, + percent_uncacheable=options.uncacheable, + progress_interval=options.progress) ] + +# next comes L1 cache, if any +if len(treespec) > 1: + prototypes.insert(0, proto_l1) + +# now add additional cache levels (if any) by scaling L1 params +for scale in treespec[:-2]: + # clone previous level and update params + prev = prototypes[0] + next = prev() + next.size = prev.size * scale + next.latency = prev.latency * 10 + next.assoc = prev.assoc * scale + next.mshrs = prev.mshrs * scale + prototypes.insert(0, next) + +# system simulated +system = System(funcmem = SimpleMemory(in_addr_map = False), + physmem = SimpleMemory(latency = "100ns")) + +def make_level(spec, prototypes, attach_obj, attach_port): + fanout = spec[0] + parent = attach_obj # use attach obj as config parent too + if len(spec) > 1 and (fanout > 1 or options.force_bus): + port = getattr(attach_obj, attach_port) + new_bus = CoherentBus(clock="500MHz", width=16) + if (port.role == 'MASTER'): + new_bus.slave = port + attach_port = "master" + else: + new_bus.master = port + attach_port = "slave" + parent.cpu_side_bus = new_bus + attach_obj = new_bus + objs = [prototypes[0]() for i in xrange(fanout)] + if len(spec) > 1: + # we just built caches, more levels to go + parent.cache = objs + for cache in objs: + cache.mem_side = getattr(attach_obj, attach_port) + make_level(spec[1:], prototypes[1:], cache, "cpu_side") + else: + # we just built the MemTest objects + parent.cpu = objs + for t in objs: + t.test = getattr(attach_obj, attach_port) + t.functional = system.funcmem.port + +make_level(treespec, prototypes, system.physmem, "port") + +# ----------------------- +# run simulation +# ----------------------- + +root = Root( full_system = False, system = system ) +if options.atomic: + root.system.mem_mode = 'atomic' +else: + root.system.mem_mode = 'timing' + +# The system port is never used in the tester so merely connect it +# to avoid problems +root.system.system_port = root.system.physmem.port + +# Not much point in this being higher than the L1 latency +m5.ticks.setGlobalFrequency('1ns') + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +exit_event = m5.simulate(options.maxtick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() diff --git a/simulators/gem5/configs/example/ruby_direct_test.py b/simulators/gem5/configs/example/ruby_direct_test.py new file mode 100644 index 00000000..f591d47e --- /dev/null +++ b/simulators/gem5/configs/example/ruby_direct_test.py @@ -0,0 +1,125 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski +# Brad Beckmann + +import m5 +from m5.objects import * +from m5.defines import buildEnv +from m5.util import addToPath +import os, optparse, sys +addToPath('../common') +addToPath('../ruby') + +import Options +import Ruby + +# Get paths we might need. It's expected this file is in m5/configs/example. +config_path = os.path.dirname(os.path.abspath(__file__)) +config_root = os.path.dirname(config_path) +m5_root = os.path.dirname(config_root) + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) + +parser.add_option("-l", "--requests", metavar="N", default=100, + help="Stop after N requests") +parser.add_option("-f", "--wakeup_freq", metavar="N", default=10, + help="Wakeup every N cycles") +parser.add_option("--test-type", type="string", default="SeriesGetx", + help="SeriesGetx|SeriesGets|Invalidate") + +# +# Add the ruby specific and protocol specific options +# +Ruby.define_options(parser) + +execfile(os.path.join(config_root, "common", "Options.py")) + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +# +# Select the direct test generator +# +if options.test_type == "SeriesGetx": + generator = SeriesRequestGenerator(num_cpus = options.num_cpus, + issue_writes = True) +elif options.test_type == "SeriesGets": + generator = SeriesRequestGenerator(num_cpus = options.num_cpus, + issue_writes = False) +elif options.test_type == "Invalidate": + generator = InvalidateGenerator(num_cpus = options.num_cpus) +else: + print "Error: unknown direct test generator" + sys.exit(1) + +# +# Create the M5 system. Note that the Memory Object isn't +# actually used by the rubytester, but is included to support the +# M5 memory size == Ruby memory size checks +# +system = System(physmem = SimpleMemory()) + +# +# Create the ruby random tester +# +system.tester = RubyDirectedTester(requests_to_complete = \ + options.requests, + generator = generator) + +Ruby.create_system(options, system) + +assert(options.num_cpus == len(system.ruby._cpu_ruby_ports)) + +for ruby_port in system.ruby._cpu_ruby_ports: + # + # Tie the ruby tester ports to the ruby cpu ports + # + system.tester.cpuPort = ruby_port.slave + +# ----------------------- +# run simulation +# ----------------------- + +root = Root( full_system = False, system = system ) +root.system.mem_mode = 'timing' + +# Not much point in this being higher than the L1 latency +m5.ticks.setGlobalFrequency('1ns') + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +exit_event = m5.simulate(options.maxtick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() diff --git a/simulators/gem5/configs/example/ruby_fs.py b/simulators/gem5/configs/example/ruby_fs.py new file mode 100644 index 00000000..35e485c7 --- /dev/null +++ b/simulators/gem5/configs/example/ruby_fs.py @@ -0,0 +1,116 @@ +# Copyright (c) 2009-2011 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +# +# Full system configuraiton for ruby +# + +import optparse +import sys + +import m5 +from m5.defines import buildEnv +from m5.objects import * +from m5.util import addToPath, fatal + +addToPath('../common') +addToPath('../ruby') + +import Ruby + +from FSConfig import * +from SysPaths import * +from Benchmarks import * +import Options +import Simulation + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) +Options.addFSOptions(parser) + +# Add the ruby specific and protocol specific options +Ruby.define_options(parser) + +(options, args) = parser.parse_args() +options.ruby = True + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +if options.benchmark: + try: + bm = Benchmarks[options.benchmark] + except KeyError: + print "Error benchmark %s has not been defined." % options.benchmark + print "Valid benchmarks are: %s" % DefinedBenchmarks + sys.exit(1) +else: + bm = [SysConfig(disk=options.disk_image, mem=options.mem_size)] + +# Check for timing mode because ruby does not support atomic accesses +if not (options.cpu_type == "detailed" or options.cpu_type == "timing"): + print >> sys.stderr, "Ruby requires TimingSimpleCPU or O3CPU!!" + sys.exit(1) +(CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options) + +CPUClass.clock = options.clock + +if buildEnv['TARGET_ISA'] == "alpha": + system = makeLinuxAlphaRubySystem(test_mem_mode, bm[0]) +elif buildEnv['TARGET_ISA'] == "x86": + system = makeLinuxX86System(test_mem_mode, options.num_cpus, bm[0], True) + Simulation.setWorkCountOptions(system, options) +else: + fatal("incapable of building non-alpha or non-x86 full system!") + +if options.kernel is not None: + system.kernel = binary(options.kernel) + +if options.script is not None: + system.readfile = options.script + +system.cpu = [CPUClass(cpu_id=i) for i in xrange(options.num_cpus)] +Ruby.create_system(options, system, system.piobus, system._dma_ports) + +for (i, cpu) in enumerate(system.cpu): + # + # Tie the cpu ports to the correct ruby system ports + # + cpu.createInterruptController() + cpu.icache_port = system.ruby._cpu_ruby_ports[i].slave + cpu.dcache_port = system.ruby._cpu_ruby_ports[i].slave + if buildEnv['TARGET_ISA'] == "x86": + cpu.itb.walker.port = system.ruby._cpu_ruby_ports[i].slave + cpu.dtb.walker.port = system.ruby._cpu_ruby_ports[i].slave + cpu.interrupts.pio = system.piobus.master + cpu.interrupts.int_master = system.piobus.slave + cpu.interrupts.int_slave = system.piobus.master + +root = Root(full_system = True, system = system) +Simulation.run(options, root, system, FutureClass) diff --git a/simulators/gem5/configs/example/ruby_mem_test.py b/simulators/gem5/configs/example/ruby_mem_test.py new file mode 100644 index 00000000..4d7932b7 --- /dev/null +++ b/simulators/gem5/configs/example/ruby_mem_test.py @@ -0,0 +1,180 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski +# Brad Beckmann + +import m5 +from m5.objects import * +from m5.defines import buildEnv +from m5.util import addToPath +import os, optparse, sys +addToPath('../common') +addToPath('../ruby') + +import Options +import Ruby + +# Get paths we might need. It's expected this file is in m5/configs/example. +config_path = os.path.dirname(os.path.abspath(__file__)) +config_root = os.path.dirname(config_path) +m5_root = os.path.dirname(config_root) + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) + +parser.add_option("-l", "--maxloads", metavar="N", default=0, + help="Stop after N loads") +parser.add_option("--progress", type="int", default=1000, + metavar="NLOADS", + help="Progress message interval " + "[default: %default]") +parser.add_option("--num-dmas", type="int", default=0, help="# of dma testers") +parser.add_option("--functional", type="int", default=0, + help="percentage of accesses that should be functional") +parser.add_option("--suppress-func-warnings", action="store_true", + help="suppress warnings when functional accesses fail") + +# +# Add the ruby specific and protocol specific options +# +Ruby.define_options(parser) + +execfile(os.path.join(config_root, "common", "Options.py")) + +(options, args) = parser.parse_args() + +# +# Set the default cache size and associativity to be very small to encourage +# races between requests and writebacks. +# +options.l1d_size="256B" +options.l1i_size="256B" +options.l2_size="512B" +options.l3_size="1kB" +options.l1d_assoc=2 +options.l1i_assoc=2 +options.l2_assoc=2 +options.l3_assoc=2 + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +block_size = 64 + +if options.num_cpus > block_size: + print "Error: Number of testers %d limited to %d because of false sharing" \ + % (options.num_cpus, block_size) + sys.exit(1) + +# +# Currently ruby does not support atomic or uncacheable accesses +# +cpus = [ MemTest(atomic = False, + max_loads = options.maxloads, + issue_dmas = False, + percent_functional = options.functional, + percent_uncacheable = 0, + progress_interval = options.progress, + suppress_func_warnings = options.suppress_func_warnings) \ + for i in xrange(options.num_cpus) ] + +system = System(cpu = cpus, + funcmem = SimpleMemory(in_addr_map = False), + physmem = SimpleMemory()) + +if options.num_dmas > 0: + dmas = [ MemTest(atomic = False, + max_loads = options.maxloads, + issue_dmas = True, + percent_functional = 0, + percent_uncacheable = 0, + progress_interval = options.progress, + suppress_func_warnings = + not options.suppress_func_warnings) \ + for i in xrange(options.num_dmas) ] + system.dma_devices = dmas +else: + dmas = [] + +dma_ports = [] +for (i, dma) in enumerate(dmas): + dma_ports.append(dma.test) +Ruby.create_system(options, system, dma_ports = dma_ports) + +# +# The tester is most effective when randomization is turned on and +# artifical delay is randomly inserted on messages +# +system.ruby.randomization = True + +assert(len(cpus) == len(system.ruby._cpu_ruby_ports)) + +for (i, cpu) in enumerate(cpus): + # + # Tie the cpu memtester ports to the correct system ports + # + cpu.test = system.ruby._cpu_ruby_ports[i].slave + cpu.functional = system.funcmem.port + + # + # Since the memtester is incredibly bursty, increase the deadlock + # threshold to 5 million cycles + # + system.ruby._cpu_ruby_ports[i].deadlock_threshold = 5000000 + + # + # Ruby doesn't need the backing image of memory when running with + # the tester. + # + system.ruby._cpu_ruby_ports[i].access_phys_mem = False + +for (i, dma) in enumerate(dmas): + # + # Tie the dma memtester ports to the correct functional port + # Note that the test port has already been connected to the dma_sequencer + # + dma.functional = system.funcmem.port + +# ----------------------- +# run simulation +# ----------------------- + +root = Root( full_system = False, system = system ) +root.system.mem_mode = 'timing' + +# Not much point in this being higher than the L1 latency +m5.ticks.setGlobalFrequency('1ns') + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +exit_event = m5.simulate(options.maxtick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() diff --git a/simulators/gem5/configs/example/ruby_network_test.py b/simulators/gem5/configs/example/ruby_network_test.py new file mode 100644 index 00000000..1d44813a --- /dev/null +++ b/simulators/gem5/configs/example/ruby_network_test.py @@ -0,0 +1,136 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2010 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski +# Tushar Krishna + +import m5 +from m5.objects import * +from m5.defines import buildEnv +from m5.util import addToPath +import os, optparse, sys +addToPath('../common') +addToPath('../ruby') + +import Options +import Ruby + +# Get paths we might need. It's expected this file is in m5/configs/example. +config_path = os.path.dirname(os.path.abspath(__file__)) +config_root = os.path.dirname(config_path) +m5_root = os.path.dirname(config_root) + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) + +parser.add_option("--synthetic", type="int", default=0, + help="Synthetic Traffic type. 0 = Uniform Random,\ + 1 = Tornado, 2 = Bit Complement") + +parser.add_option("-i", "--injectionrate", type="float", default=0.1, + metavar="I", + help="Injection rate in packets per cycle per node. \ + Takes decimal value between 0 to 1 (eg. 0.225). \ + Number of digits after 0 depends upon --precision.") + +parser.add_option("--precision", type="int", default=3, + help="Number of digits of precision after decimal point\ + for injection rate") + +parser.add_option("--sim-cycles", type="int", default=1000, + help="Number of simulation cycles") + +parser.add_option("--fixed-pkts", action="store_true", + help="Network_test: inject --maxpackets and stop") + +parser.add_option("--maxpackets", type="int", default=1, + help="Stop injecting after --maxpackets. \ + Works only with --fixed-pkts") + +# +# Add the ruby specific and protocol specific options +# +Ruby.define_options(parser) + +execfile(os.path.join(config_root, "common", "Options.py")) + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +block_size = 64 + +if options.num_cpus > block_size: + print "Error: Number of cores %d limited to %d because of false sharing" \ + % (options.num_cpus, block_size) + sys.exit(1) + + +cpus = [ NetworkTest(fixed_pkts=options.fixed_pkts, + max_packets=options.maxpackets, + sim_cycles=options.sim_cycles, + traffic_type=options.synthetic, + inj_rate=options.injectionrate, + precision=options.precision, + num_memories=options.num_dirs) \ + for i in xrange(options.num_cpus) ] + +# create the desired simulated system +system = System(cpu = cpus, + physmem = SimpleMemory()) + +Ruby.create_system(options, system) + +i = 0 +for ruby_port in system.ruby._cpu_ruby_ports: + # + # Tie the cpu test ports to the ruby cpu port + # + cpus[i].test = ruby_port.slave + ruby_port.access_phys_mem = False + + i += 1 + +# ----------------------- +# run simulation +# ----------------------- + +root = Root( full_system = False, system = system ) +root.system.mem_mode = 'timing' + +# Not much point in this being higher than the L1 latency +m5.ticks.setGlobalFrequency('1ns') + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +exit_event = m5.simulate(options.maxtick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() diff --git a/simulators/gem5/configs/example/ruby_random_test.py b/simulators/gem5/configs/example/ruby_random_test.py new file mode 100644 index 00000000..b4d32b72 --- /dev/null +++ b/simulators/gem5/configs/example/ruby_random_test.py @@ -0,0 +1,149 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski +# Brad Beckmann + +import m5 +from m5.objects import * +from m5.defines import buildEnv +from m5.util import addToPath +import os, optparse, sys +addToPath('../common') +addToPath('../ruby') + +import Options +import Ruby + +# Get paths we might need. It's expected this file is in m5/configs/example. +config_path = os.path.dirname(os.path.abspath(__file__)) +config_root = os.path.dirname(config_path) +m5_root = os.path.dirname(config_root) + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) + +parser.add_option("-l", "--checks", metavar="N", default=100, + help="Stop after N checks (loads)") +parser.add_option("-f", "--wakeup_freq", metavar="N", default=10, + help="Wakeup every N cycles") + +# +# Add the ruby specific and protocol specific options +# +Ruby.define_options(parser) + +execfile(os.path.join(config_root, "common", "Options.py")) + +(options, args) = parser.parse_args() + +# +# Set the default cache size and associativity to be very small to encourage +# races between requests and writebacks. +# +options.l1d_size="256B" +options.l1i_size="256B" +options.l2_size="512B" +options.l3_size="1kB" +options.l1d_assoc=2 +options.l1i_assoc=2 +options.l2_assoc=2 +options.l3_assoc=2 + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +# +# Create the ruby random tester +# + +# Check the protocol +check_flush = False +if buildEnv['PROTOCOL'] == 'MOESI_hammer': + check_flush = True + +tester = RubyTester(check_flush = check_flush, + checks_to_complete = options.checks, + wakeup_frequency = options.wakeup_freq, + num_cpus = options.num_cpus) + +# +# Create the M5 system. Note that the Memory Object isn't +# actually used by the rubytester, but is included to support the +# M5 memory size == Ruby memory size checks +# +system = System(tester = tester, physmem = SimpleMemory()) + +Ruby.create_system(options, system) + +assert(options.num_cpus == len(system.ruby._cpu_ruby_ports)) + +# +# The tester is most effective when randomization is turned on and +# artifical delay is randomly inserted on messages +# +system.ruby.randomization = True + +for ruby_port in system.ruby._cpu_ruby_ports: + # + # Tie the ruby tester ports to the ruby cpu read and write ports + # + if ruby_port.support_data_reqs: + tester.cpuDataPort = ruby_port.slave + if ruby_port.support_inst_reqs: + tester.cpuInstPort = ruby_port.slave + + # + # Tell each sequencer this is the ruby tester so that it + # copies the subblock back to the checker + # + ruby_port.using_ruby_tester = True + + # + # Ruby doesn't need the backing image of memory when running with + # the tester. + # + ruby_port.access_phys_mem = False + +# ----------------------- +# run simulation +# ----------------------- + +root = Root( full_system = False, system = system ) +root.system.mem_mode = 'timing' + +# Not much point in this being higher than the L1 latency +m5.ticks.setGlobalFrequency('1ns') + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +exit_event = m5.simulate(options.maxtick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() diff --git a/simulators/gem5/configs/example/se.py b/simulators/gem5/configs/example/se.py new file mode 100644 index 00000000..83abbd2f --- /dev/null +++ b/simulators/gem5/configs/example/se.py @@ -0,0 +1,201 @@ +# Copyright (c) 2012 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2006-2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt + +# Simple test script +# +# "m5 test.py" + +import optparse +import sys + +import m5 +from m5.defines import buildEnv +from m5.objects import * +from m5.util import addToPath, fatal + +addToPath('../common') +addToPath('../ruby') + +import Options +import Ruby +import Simulation +import CacheConfig +from Caches import * +from cpu2000 import * + +parser = optparse.OptionParser() +Options.addCommonOptions(parser) +Options.addSEOptions(parser) + +if '--ruby' in sys.argv: + Ruby.define_options(parser) + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +multiprocesses = [] +apps = [] + +if options.bench: + apps = options.bench.split("-") + if len(apps) != options.num_cpus: + print "number of benchmarks not equal to set num_cpus!" + sys.exit(1) + + for app in apps: + try: + if buildEnv['TARGET_ISA'] == 'alpha': + exec("workload = %s('alpha', 'tru64', 'ref')" % app) + else: + exec("workload = %s(buildEnv['TARGET_ISA'], 'linux', 'ref')" % app) + multiprocesses.append(workload.makeLiveProcess()) + except: + print >>sys.stderr, "Unable to find workload for %s: %s" % (buildEnv['TARGET_ISA'], app) + sys.exit(1) +elif options.cmd: + process = LiveProcess() + process.executable = options.cmd + process.cmd = [options.cmd] + options.options.split() + multiprocesses.append(process) +else: + print >> sys.stderr, "No workload specified. Exiting!\n" + sys.exit(1) + + +if options.input != "": + process.input = options.input +if options.output != "": + process.output = options.output +if options.errout != "": + process.errout = options.errout + + +# By default, set workload to path of user-specified binary +workloads = options.cmd +numThreads = 1 + +if options.cpu_type == "detailed" or options.cpu_type == "inorder": + #check for SMT workload + workloads = options.cmd.split(';') + if len(workloads) > 1: + process = [] + smt_idx = 0 + inputs = [] + outputs = [] + errouts = [] + + if options.input != "": + inputs = options.input.split(';') + if options.output != "": + outputs = options.output.split(';') + if options.errout != "": + errouts = options.errout.split(';') + + for wrkld in workloads: + smt_process = LiveProcess() + smt_process.executable = wrkld + smt_process.cmd = wrkld + " " + options.options + if inputs and inputs[smt_idx]: + smt_process.input = inputs[smt_idx] + if outputs and outputs[smt_idx]: + smt_process.output = outputs[smt_idx] + if errouts and errouts[smt_idx]: + smt_process.errout = errouts[smt_idx] + process += [smt_process, ] + smt_idx += 1 + numThreads = len(workloads) + +(CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options) +CPUClass.clock = '2GHz' +CPUClass.numThreads = numThreads; + +np = options.num_cpus + +system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)], + physmem = SimpleMemory(range=AddrRange("512MB")), + membus = CoherentBus(), mem_mode = test_mem_mode) + +# Sanity check +if options.fastmem and (options.caches or options.l2cache): + fatal("You cannot use fastmem in combination with caches!") + +for i in xrange(np): + if len(multiprocesses) == 1: + system.cpu[i].workload = multiprocesses[0] + else: + system.cpu[i].workload = multiprocesses[i] + + if options.fastmem: + system.cpu[i].fastmem = True + + if options.checker: + system.cpu[i].addCheckerCpu() + +if options.ruby: + if not (options.cpu_type == "detailed" or options.cpu_type == "timing"): + print >> sys.stderr, "Ruby requires TimingSimpleCPU or O3CPU!!" + sys.exit(1) + + options.use_map = True + Ruby.create_system(options, system) + assert(options.num_cpus == len(system.ruby._cpu_ruby_ports)) + + for i in xrange(np): + ruby_port = system.ruby._cpu_ruby_ports[i] + + # Create the interrupt controller and connect its ports to Ruby + system.cpu[i].createInterruptController() + system.cpu[i].interrupts.pio = ruby_port.master + system.cpu[i].interrupts.int_master = ruby_port.slave + system.cpu[i].interrupts.int_slave = ruby_port.master + + # Connect the cpu's cache ports to Ruby + system.cpu[i].icache_port = ruby_port.slave + system.cpu[i].dcache_port = ruby_port.slave +else: + system.system_port = system.membus.slave + system.physmem.port = system.membus.master + CacheConfig.config_cache(options, system) + +root = Root(full_system = False, system = system) +Simulation.run(options, root, system, FutureClass) diff --git a/simulators/gem5/configs/ruby/MESI_CMP_directory.py b/simulators/gem5/configs/ruby/MESI_CMP_directory.py new file mode 100644 index 00000000..cd503ddc --- /dev/null +++ b/simulators/gem5/configs/ruby/MESI_CMP_directory.py @@ -0,0 +1,188 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import math +import m5 +from m5.objects import * +from m5.defines import buildEnv + +# +# Note: the L1 Cache latency is only used by the sequencer on fast path hits +# +class L1Cache(RubyCache): + latency = 3 + +# +# Note: the L2 Cache latency is not currently used +# +class L2Cache(RubyCache): + latency = 15 + +def define_options(parser): + return + +def create_system(options, system, piobus, dma_ports, ruby_system): + + if buildEnv['PROTOCOL'] != 'MESI_CMP_directory': + panic("This script requires the MESI_CMP_directory protocol to be built.") + + cpu_sequencers = [] + + # + # The ruby network creation expects the list of nodes in the system to be + # consistent with the NetDest list. Therefore the l1 controller nodes must be + # listed before the directory nodes and directory nodes before dma nodes, etc. + # + l1_cntrl_nodes = [] + l2_cntrl_nodes = [] + dir_cntrl_nodes = [] + dma_cntrl_nodes = [] + + # + # Must create the individual controllers before the network to ensure the + # controller constructors are called before the network constructor + # + l2_bits = int(math.log(options.num_l2caches, 2)) + block_size_bits = int(math.log(options.cacheline_size, 2)) + + cntrl_count = 0 + + for i in xrange(options.num_cpus): + # + # First create the Ruby objects associated with this cpu + # + l1i_cache = L1Cache(size = options.l1i_size, + assoc = options.l1i_assoc, + start_index_bit = block_size_bits) + l1d_cache = L1Cache(size = options.l1d_size, + assoc = options.l1d_assoc, + start_index_bit = block_size_bits) + + l1_cntrl = L1Cache_Controller(version = i, + cntrl_id = cntrl_count, + L1IcacheMemory = l1i_cache, + L1DcacheMemory = l1d_cache, + l2_select_num_bits = l2_bits, + send_evictions = ( + options.cpu_type == "detailed"), + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + ruby_system = ruby_system) + + l1_cntrl.sequencer = cpu_seq + + if piobus != None: + cpu_seq.pio_port = piobus.slave + + exec("system.l1_cntrl%d = l1_cntrl" % i) + + # + # Add controllers and sequencers to the appropriate lists + # + cpu_sequencers.append(cpu_seq) + l1_cntrl_nodes.append(l1_cntrl) + + cntrl_count += 1 + + l2_index_start = block_size_bits + l2_bits + + for i in xrange(options.num_l2caches): + # + # First create the Ruby objects associated with this cpu + # + l2_cache = L2Cache(size = options.l2_size, + assoc = options.l2_assoc, + start_index_bit = l2_index_start) + + l2_cntrl = L2Cache_Controller(version = i, + cntrl_id = cntrl_count, + L2cacheMemory = l2_cache, + ruby_system = ruby_system) + + exec("system.l2_cntrl%d = l2_cntrl" % i) + l2_cntrl_nodes.append(l2_cntrl) + + cntrl_count += 1 + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + mem_module_size = phys_mem_size / options.num_dirs + + for i in xrange(options.num_dirs): + # + # Create the Ruby objects associated with the directory controller + # + + mem_cntrl = RubyMemoryControl(version = i) + + dir_size = MemorySize('0B') + dir_size.value = mem_module_size + + dir_cntrl = Directory_Controller(version = i, + cntrl_id = cntrl_count, + directory = \ + RubyDirectoryMemory(version = i, + size = dir_size, + use_map = + options.use_map), + memBuffer = mem_cntrl, + ruby_system = ruby_system) + + exec("system.dir_cntrl%d = dir_cntrl" % i) + dir_cntrl_nodes.append(dir_cntrl) + + cntrl_count += 1 + + for i, dma_port in enumerate(dma_ports): + # + # Create the Ruby objects associated with the dma controller + # + dma_seq = DMASequencer(version = i, + ruby_system = ruby_system) + + dma_cntrl = DMA_Controller(version = i, + cntrl_id = cntrl_count, + dma_sequencer = dma_seq, + ruby_system = ruby_system) + + exec("system.dma_cntrl%d = dma_cntrl" % i) + exec("system.dma_cntrl%d.dma_sequencer.slave = dma_port" % i) + dma_cntrl_nodes.append(dma_cntrl) + cntrl_count += 1 + + all_cntrls = l1_cntrl_nodes + \ + l2_cntrl_nodes + \ + dir_cntrl_nodes + \ + dma_cntrl_nodes + + return (cpu_sequencers, dir_cntrl_nodes, all_cntrls) diff --git a/simulators/gem5/configs/ruby/MI_example.py b/simulators/gem5/configs/ruby/MI_example.py new file mode 100644 index 00000000..de82c38f --- /dev/null +++ b/simulators/gem5/configs/ruby/MI_example.py @@ -0,0 +1,158 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import math +import m5 +from m5.objects import * +from m5.defines import buildEnv + +# +# Note: the cache latency is only used by the sequencer on fast path hits +# +class Cache(RubyCache): + latency = 3 + +def define_options(parser): + return + +def create_system(options, system, piobus, dma_ports, ruby_system): + + if buildEnv['PROTOCOL'] != 'MI_example': + panic("This script requires the MI_example protocol to be built.") + + cpu_sequencers = [] + + # + # The ruby network creation expects the list of nodes in the system to be + # consistent with the NetDest list. Therefore the l1 controller nodes must be + # listed before the directory nodes and directory nodes before dma nodes, etc. + # + l1_cntrl_nodes = [] + dir_cntrl_nodes = [] + dma_cntrl_nodes = [] + + # + # Must create the individual controllers before the network to ensure the + # controller constructors are called before the network constructor + # + block_size_bits = int(math.log(options.cacheline_size, 2)) + + cntrl_count = 0 + + for i in xrange(options.num_cpus): + # + # First create the Ruby objects associated with this cpu + # Only one cache exists for this protocol, so by default use the L1D + # config parameters. + # + cache = Cache(size = options.l1d_size, + assoc = options.l1d_assoc, + start_index_bit = block_size_bits) + + # + # Only one unified L1 cache exists. Can cache instructions and data. + # + l1_cntrl = L1Cache_Controller(version = i, + cntrl_id = cntrl_count, + cacheMemory = cache, + send_evictions = ( + options.cpu_type == "detailed"), + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = cache, + dcache = cache, + ruby_system = ruby_system) + + l1_cntrl.sequencer = cpu_seq + + if piobus != None: + cpu_seq.pio_port = piobus.slave + + exec("system.l1_cntrl%d = l1_cntrl" % i) + # + # Add controllers and sequencers to the appropriate lists + # + cpu_sequencers.append(cpu_seq) + l1_cntrl_nodes.append(l1_cntrl) + + cntrl_count += 1 + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + mem_module_size = phys_mem_size / options.num_dirs + + for i in xrange(options.num_dirs): + # + # Create the Ruby objects associated with the directory controller + # + + mem_cntrl = RubyMemoryControl(version = i) + + dir_size = MemorySize('0B') + dir_size.value = mem_module_size + + dir_cntrl = Directory_Controller(version = i, + cntrl_id = cntrl_count, + directory = \ + RubyDirectoryMemory( \ + version = i, + size = dir_size, + use_map = options.use_map, + map_levels = \ + options.map_levels), + memBuffer = mem_cntrl, + ruby_system = ruby_system) + + exec("system.dir_cntrl%d = dir_cntrl" % i) + dir_cntrl_nodes.append(dir_cntrl) + + cntrl_count += 1 + + for i, dma_port in enumerate(dma_ports): + # + # Create the Ruby objects associated with the dma controller + # + dma_seq = DMASequencer(version = i, + ruby_system = ruby_system) + + dma_cntrl = DMA_Controller(version = i, + cntrl_id = cntrl_count, + dma_sequencer = dma_seq, + ruby_system = ruby_system) + + exec("system.dma_cntrl%d = dma_cntrl" % i) + exec("system.dma_cntrl%d.dma_sequencer.slave = dma_port" % i) + dma_cntrl_nodes.append(dma_cntrl) + cntrl_count += 1 + + all_cntrls = l1_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes + + return (cpu_sequencers, dir_cntrl_nodes, all_cntrls) diff --git a/simulators/gem5/configs/ruby/MOESI_CMP_directory.py b/simulators/gem5/configs/ruby/MOESI_CMP_directory.py new file mode 100644 index 00000000..10eeaf21 --- /dev/null +++ b/simulators/gem5/configs/ruby/MOESI_CMP_directory.py @@ -0,0 +1,185 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import math +import m5 +from m5.objects import * +from m5.defines import buildEnv + +# +# Note: the L1 Cache latency is only used by the sequencer on fast path hits +# +class L1Cache(RubyCache): + latency = 3 + +# +# Note: the L2 Cache latency is not currently used +# +class L2Cache(RubyCache): + latency = 15 + +def define_options(parser): + return + +def create_system(options, system, piobus, dma_ports, ruby_system): + + if buildEnv['PROTOCOL'] != 'MOESI_CMP_directory': + panic("This script requires the MOESI_CMP_directory protocol to be built.") + + cpu_sequencers = [] + + # + # The ruby network creation expects the list of nodes in the system to be + # consistent with the NetDest list. Therefore the l1 controller nodes must be + # listed before the directory nodes and directory nodes before dma nodes, etc. + # + l1_cntrl_nodes = [] + l2_cntrl_nodes = [] + dir_cntrl_nodes = [] + dma_cntrl_nodes = [] + + # + # Must create the individual controllers before the network to ensure the + # controller constructors are called before the network constructor + # + l2_bits = int(math.log(options.num_l2caches, 2)) + block_size_bits = int(math.log(options.cacheline_size, 2)) + + cntrl_count = 0 + + for i in xrange(options.num_cpus): + # + # First create the Ruby objects associated with this cpu + # + l1i_cache = L1Cache(size = options.l1i_size, + assoc = options.l1i_assoc, + start_index_bit = block_size_bits) + l1d_cache = L1Cache(size = options.l1d_size, + assoc = options.l1d_assoc, + start_index_bit = block_size_bits) + + l1_cntrl = L1Cache_Controller(version = i, + cntrl_id = cntrl_count, + L1IcacheMemory = l1i_cache, + L1DcacheMemory = l1d_cache, + l2_select_num_bits = l2_bits, + send_evictions = ( + options.cpu_type == "detailed"), + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + ruby_system = ruby_system) + + l1_cntrl.sequencer = cpu_seq + + if piobus != None: + cpu_seq.pio_port = piobus.slave + + exec("system.l1_cntrl%d = l1_cntrl" % i) + # + # Add controllers and sequencers to the appropriate lists + # + cpu_sequencers.append(cpu_seq) + l1_cntrl_nodes.append(l1_cntrl) + + cntrl_count += 1 + + l2_index_start = block_size_bits + l2_bits + + for i in xrange(options.num_l2caches): + # + # First create the Ruby objects associated with this cpu + # + l2_cache = L2Cache(size = options.l2_size, + assoc = options.l2_assoc, + start_index_bit = l2_index_start) + + l2_cntrl = L2Cache_Controller(version = i, + cntrl_id = cntrl_count, + L2cacheMemory = l2_cache, + ruby_system = ruby_system) + + exec("system.l2_cntrl%d = l2_cntrl" % i) + l2_cntrl_nodes.append(l2_cntrl) + + cntrl_count += 1 + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + mem_module_size = phys_mem_size / options.num_dirs + + for i in xrange(options.num_dirs): + # + # Create the Ruby objects associated with the directory controller + # + + mem_cntrl = RubyMemoryControl(version = i) + + dir_size = MemorySize('0B') + dir_size.value = mem_module_size + + dir_cntrl = Directory_Controller(version = i, + cntrl_id = cntrl_count, + directory = \ + RubyDirectoryMemory(version = i, + size = dir_size), + memBuffer = mem_cntrl, + ruby_system = ruby_system) + + exec("system.dir_cntrl%d = dir_cntrl" % i) + dir_cntrl_nodes.append(dir_cntrl) + + cntrl_count += 1 + + for i, dma_port in enumerate(dma_ports): + # + # Create the Ruby objects associated with the dma controller + # + dma_seq = DMASequencer(version = i, + ruby_system = ruby_system) + + dma_cntrl = DMA_Controller(version = i, + cntrl_id = cntrl_count, + dma_sequencer = dma_seq, + ruby_system = ruby_system) + + exec("system.dma_cntrl%d = dma_cntrl" % i) + exec("system.dma_cntrl%d.dma_sequencer.slave = dma_port" % i) + dma_cntrl_nodes.append(dma_cntrl) + cntrl_count += 1 + + all_cntrls = l1_cntrl_nodes + \ + l2_cntrl_nodes + \ + dir_cntrl_nodes + \ + dma_cntrl_nodes + + return (cpu_sequencers, dir_cntrl_nodes, all_cntrls) diff --git a/simulators/gem5/configs/ruby/MOESI_CMP_token.py b/simulators/gem5/configs/ruby/MOESI_CMP_token.py new file mode 100644 index 00000000..4da7d7ad --- /dev/null +++ b/simulators/gem5/configs/ruby/MOESI_CMP_token.py @@ -0,0 +1,209 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import math +import m5 +from m5.objects import * +from m5.defines import buildEnv + +# +# Note: the L1 Cache latency is only used by the sequencer on fast path hits +# +class L1Cache(RubyCache): + latency = 2 + +# +# Note: the L2 Cache latency is not currently used +# +class L2Cache(RubyCache): + latency = 10 + +def define_options(parser): + parser.add_option("--l1-retries", type="int", default=1, + help="Token_CMP: # of l1 retries before going persistent") + parser.add_option("--timeout-latency", type="int", default=300, + help="Token_CMP: cycles until issuing again"); + parser.add_option("--disable-dyn-timeouts", action="store_true", + help="Token_CMP: disable dyanimc timeouts, use fixed latency instead") + parser.add_option("--allow-atomic-migration", action="store_true", + help="allow migratory sharing for atomic only accessed blocks") + +def create_system(options, system, piobus, dma_ports, ruby_system): + + if buildEnv['PROTOCOL'] != 'MOESI_CMP_token': + panic("This script requires the MOESI_CMP_token protocol to be built.") + + # + # number of tokens that the owner passes to requests so that shared blocks can + # respond to read requests + # + n_tokens = options.num_cpus + 1 + + cpu_sequencers = [] + + # + # The ruby network creation expects the list of nodes in the system to be + # consistent with the NetDest list. Therefore the l1 controller nodes must be + # listed before the directory nodes and directory nodes before dma nodes, etc. + # + l1_cntrl_nodes = [] + l2_cntrl_nodes = [] + dir_cntrl_nodes = [] + dma_cntrl_nodes = [] + + # + # Must create the individual controllers before the network to ensure the + # controller constructors are called before the network constructor + # + l2_bits = int(math.log(options.num_l2caches, 2)) + block_size_bits = int(math.log(options.cacheline_size, 2)) + + cntrl_count = 0 + + for i in xrange(options.num_cpus): + # + # First create the Ruby objects associated with this cpu + # + l1i_cache = L1Cache(size = options.l1i_size, + assoc = options.l1i_assoc, + start_index_bit = block_size_bits) + l1d_cache = L1Cache(size = options.l1d_size, + assoc = options.l1d_assoc, + start_index_bit = block_size_bits) + + l1_cntrl = L1Cache_Controller(version = i, + cntrl_id = cntrl_count, + L1IcacheMemory = l1i_cache, + L1DcacheMemory = l1d_cache, + l2_select_num_bits = l2_bits, + N_tokens = n_tokens, + retry_threshold = \ + options.l1_retries, + fixed_timeout_latency = \ + options.timeout_latency, + dynamic_timeout_enabled = \ + not options.disable_dyn_timeouts, + no_mig_atomic = not \ + options.allow_atomic_migration, + send_evictions = ( + options.cpu_type == "detailed"), + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + ruby_system = ruby_system) + + l1_cntrl.sequencer = cpu_seq + + if piobus != None: + cpu_seq.pio_port = piobus.slave + + exec("system.l1_cntrl%d = l1_cntrl" % i) + # + # Add controllers and sequencers to the appropriate lists + # + cpu_sequencers.append(cpu_seq) + l1_cntrl_nodes.append(l1_cntrl) + + cntrl_count += 1 + + l2_index_start = block_size_bits + l2_bits + + for i in xrange(options.num_l2caches): + # + # First create the Ruby objects associated with this cpu + # + l2_cache = L2Cache(size = options.l2_size, + assoc = options.l2_assoc, + start_index_bit = l2_index_start) + + l2_cntrl = L2Cache_Controller(version = i, + cntrl_id = cntrl_count, + L2cacheMemory = l2_cache, + N_tokens = n_tokens, + ruby_system = ruby_system) + + exec("system.l2_cntrl%d = l2_cntrl" % i) + l2_cntrl_nodes.append(l2_cntrl) + + cntrl_count += 1 + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + mem_module_size = phys_mem_size / options.num_dirs + + for i in xrange(options.num_dirs): + # + # Create the Ruby objects associated with the directory controller + # + + mem_cntrl = RubyMemoryControl(version = i) + + dir_size = MemorySize('0B') + dir_size.value = mem_module_size + + dir_cntrl = Directory_Controller(version = i, + cntrl_id = cntrl_count, + directory = \ + RubyDirectoryMemory(version = i, + size = dir_size), + memBuffer = mem_cntrl, + l2_select_num_bits = l2_bits, + ruby_system = ruby_system) + + exec("system.dir_cntrl%d = dir_cntrl" % i) + dir_cntrl_nodes.append(dir_cntrl) + + cntrl_count += 1 + + for i, dma_port in enumerate(dma_ports): + # + # Create the Ruby objects associated with the dma controller + # + dma_seq = DMASequencer(version = i, + ruby_system = ruby_system) + + dma_cntrl = DMA_Controller(version = i, + cntrl_id = cntrl_count, + dma_sequencer = dma_seq, + ruby_system = ruby_system) + + exec("system.dma_cntrl%d = dma_cntrl" % i) + exec("system.dma_cntrl%d.dma_sequencer.slave = dma_port" % i) + dma_cntrl_nodes.append(dma_cntrl) + cntrl_count += 1 + + all_cntrls = l1_cntrl_nodes + \ + l2_cntrl_nodes + \ + dir_cntrl_nodes + \ + dma_cntrl_nodes + + return (cpu_sequencers, dir_cntrl_nodes, all_cntrls) diff --git a/simulators/gem5/configs/ruby/MOESI_hammer.py b/simulators/gem5/configs/ruby/MOESI_hammer.py new file mode 100644 index 00000000..62229628 --- /dev/null +++ b/simulators/gem5/configs/ruby/MOESI_hammer.py @@ -0,0 +1,222 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import math +import m5 +from m5.objects import * +from m5.defines import buildEnv + +# +# Note: the L1 Cache latency is only used by the sequencer on fast path hits +# +class L1Cache(RubyCache): + latency = 2 + +# +# Note: the L2 Cache latency is not currently used +# +class L2Cache(RubyCache): + latency = 10 + +# +# Probe filter is a cache, latency is not used +# +class ProbeFilter(RubyCache): + latency = 1 + +def define_options(parser): + parser.add_option("--allow-atomic-migration", action="store_true", + help="allow migratory sharing for atomic only accessed blocks") + parser.add_option("--pf-on", action="store_true", + help="Hammer: enable Probe Filter") + parser.add_option("--dir-on", action="store_true", + help="Hammer: enable Full-bit Directory") + +def create_system(options, system, piobus, dma_ports, ruby_system): + + if buildEnv['PROTOCOL'] != 'MOESI_hammer': + panic("This script requires the MOESI_hammer protocol to be built.") + + cpu_sequencers = [] + + # + # The ruby network creation expects the list of nodes in the system to be + # consistent with the NetDest list. Therefore the l1 controller nodes must be + # listed before the directory nodes and directory nodes before dma nodes, etc. + # + l1_cntrl_nodes = [] + dir_cntrl_nodes = [] + dma_cntrl_nodes = [] + + # + # Must create the individual controllers before the network to ensure the + # controller constructors are called before the network constructor + # + block_size_bits = int(math.log(options.cacheline_size, 2)) + + cntrl_count = 0 + + for i in xrange(options.num_cpus): + # + # First create the Ruby objects associated with this cpu + # + l1i_cache = L1Cache(size = options.l1i_size, + assoc = options.l1i_assoc, + start_index_bit = block_size_bits, + is_icache = True) + l1d_cache = L1Cache(size = options.l1d_size, + assoc = options.l1d_assoc, + start_index_bit = block_size_bits) + l2_cache = L2Cache(size = options.l2_size, + assoc = options.l2_assoc, + start_index_bit = block_size_bits) + + l1_cntrl = L1Cache_Controller(version = i, + cntrl_id = cntrl_count, + L1IcacheMemory = l1i_cache, + L1DcacheMemory = l1d_cache, + L2cacheMemory = l2_cache, + no_mig_atomic = not \ + options.allow_atomic_migration, + send_evictions = ( + options.cpu_type == "detailed"), + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + ruby_system = ruby_system) + + l1_cntrl.sequencer = cpu_seq + + if piobus != None: + cpu_seq.pio_port = piobus.slave + + if options.recycle_latency: + l1_cntrl.recycle_latency = options.recycle_latency + + exec("system.l1_cntrl%d = l1_cntrl" % i) + # + # Add controllers and sequencers to the appropriate lists + # + cpu_sequencers.append(cpu_seq) + l1_cntrl_nodes.append(l1_cntrl) + + cntrl_count += 1 + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + mem_module_size = phys_mem_size / options.num_dirs + + # + # determine size and index bits for probe filter + # By default, the probe filter size is configured to be twice the + # size of the L2 cache. + # + pf_size = MemorySize(options.l2_size) + pf_size.value = pf_size.value * 2 + dir_bits = int(math.log(options.num_dirs, 2)) + pf_bits = int(math.log(pf_size.value, 2)) + if options.numa_high_bit: + if options.numa_high_bit > 0: + # if numa high bit explicitly set, make sure it does not overlap + # with the probe filter index + assert(options.numa_high_bit - dir_bits > pf_bits) + + # set the probe filter start bit to just above the block offset + pf_start_bit = 6 + else: + if dir_bits > 0: + pf_start_bit = dir_bits + 5 + else: + pf_start_bit = 6 + + for i in xrange(options.num_dirs): + # + # Create the Ruby objects associated with the directory controller + # + + mem_cntrl = RubyMemoryControl(version = i) + + dir_size = MemorySize('0B') + dir_size.value = mem_module_size + + pf = ProbeFilter(size = pf_size, assoc = 4, + start_index_bit = pf_start_bit) + + dir_cntrl = Directory_Controller(version = i, + cntrl_id = cntrl_count, + directory = \ + RubyDirectoryMemory( \ + version = i, + size = dir_size, + use_map = options.use_map, + map_levels = \ + options.map_levels, + numa_high_bit = \ + options.numa_high_bit), + probeFilter = pf, + memBuffer = mem_cntrl, + probe_filter_enabled = options.pf_on, + full_bit_dir_enabled = options.dir_on, + ruby_system = ruby_system) + + if options.recycle_latency: + dir_cntrl.recycle_latency = options.recycle_latency + + exec("system.dir_cntrl%d = dir_cntrl" % i) + dir_cntrl_nodes.append(dir_cntrl) + + cntrl_count += 1 + + for i, dma_port in enumerate(dma_ports): + # + # Create the Ruby objects associated with the dma controller + # + dma_seq = DMASequencer(version = i, + ruby_system = ruby_system) + + dma_cntrl = DMA_Controller(version = i, + cntrl_id = cntrl_count, + dma_sequencer = dma_seq, + ruby_system = ruby_system) + + exec("system.dma_cntrl%d = dma_cntrl" % i) + exec("system.dma_cntrl%d.dma_sequencer.slave = dma_port" % i) + dma_cntrl_nodes.append(dma_cntrl) + + if options.recycle_latency: + dma_cntrl.recycle_latency = options.recycle_latency + + cntrl_count += 1 + + all_cntrls = l1_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes + + return (cpu_sequencers, dir_cntrl_nodes, all_cntrls) diff --git a/simulators/gem5/configs/ruby/Network_test.py b/simulators/gem5/configs/ruby/Network_test.py new file mode 100644 index 00000000..b84fabde --- /dev/null +++ b/simulators/gem5/configs/ruby/Network_test.py @@ -0,0 +1,138 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import m5 +from m5.objects import * +from m5.defines import buildEnv +from m5.util import addToPath + +# +# Note: the cache latency is only used by the sequencer on fast path hits +# +class Cache(RubyCache): + latency = 3 + +def define_options(parser): + return + +def create_system(options, system, piobus, dma_ports, ruby_system): + + if buildEnv['PROTOCOL'] != 'Network_test': + panic("This script requires the Network_test protocol to be built.") + + cpu_sequencers = [] + + # + # The Garnet tester protocol does not support fs nor dma + # + assert(piobus == None) + assert(dma_ports == []) + + # + # The ruby network creation expects the list of nodes in the system to be + # consistent with the NetDest list. Therefore the l1 controller nodes must be + # listed before the directory nodes and directory nodes before dma nodes, etc. + # + l1_cntrl_nodes = [] + dir_cntrl_nodes = [] + + # + # Must create the individual controllers before the network to ensure the + # controller constructors are called before the network constructor + # + + cntrl_count = 0 + + for i in xrange(options.num_cpus): + # + # First create the Ruby objects associated with this cpu + # Only one cache exists for this protocol, so by default use the L1D + # config parameters. + # + cache = Cache(size = options.l1d_size, + assoc = options.l1d_assoc) + + # + # Only one unified L1 cache exists. Can cache instructions and data. + # + l1_cntrl = L1Cache_Controller(version = i, + cntrl_id = cntrl_count, + cacheMemory = cache, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(icache = cache, + dcache = cache, + using_network_tester = True, + ruby_system = ruby_system) + + l1_cntrl.sequencer = cpu_seq + + if piobus != None: + cpu_seq.pio_port = piobus.slave + + exec("system.l1_cntrl%d = l1_cntrl" % i) + # + # Add controllers and sequencers to the appropriate lists + # + cpu_sequencers.append(cpu_seq) + l1_cntrl_nodes.append(l1_cntrl) + + cntrl_count += 1 + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + mem_module_size = phys_mem_size / options.num_dirs + + for i in xrange(options.num_dirs): + # + # Create the Ruby objects associated with the directory controller + # + + mem_cntrl = RubyMemoryControl(version = i) + + dir_size = MemorySize('0B') + dir_size.value = mem_module_size + + dir_cntrl = Directory_Controller(version = i, + cntrl_id = cntrl_count, + directory = \ + RubyDirectoryMemory(version = i, + size = dir_size), + memBuffer = mem_cntrl, + ruby_system = ruby_system) + + exec("system.dir_cntrl%d = dir_cntrl" % i) + dir_cntrl_nodes.append(dir_cntrl) + + cntrl_count += 1 + + all_cntrls = l1_cntrl_nodes + dir_cntrl_nodes + + return (cpu_sequencers, dir_cntrl_nodes, all_cntrls) diff --git a/simulators/gem5/configs/ruby/Ruby.py b/simulators/gem5/configs/ruby/Ruby.py new file mode 100644 index 00000000..87939fac --- /dev/null +++ b/simulators/gem5/configs/ruby/Ruby.py @@ -0,0 +1,189 @@ +# Copyright (c) 2012 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Brad Beckmann + +import math +import m5 +from m5.objects import * +from m5.defines import buildEnv + +def define_options(parser): + # By default, ruby uses the simple timing cpu + parser.set_defaults(cpu_type="timing") + + # ruby network options + parser.add_option("--topology", type="string", default="Crossbar", + help="check src/mem/ruby/network/topologies for complete set") + parser.add_option("--mesh-rows", type="int", default=1, + help="the number of rows in the mesh topology") + parser.add_option("--garnet-network", type="string", default=None, + help="'fixed'|'flexible'") + parser.add_option("--network-fault-model", action="store_true", default=False, + help="enable network fault model: see src/mem/ruby/network/fault_model/") + + # ruby mapping options + parser.add_option("--numa-high-bit", type="int", default=0, + help="high order address bit to use for numa mapping. " \ + "0 = highest bit, not specified = lowest bit") + + # ruby sparse memory options + parser.add_option("--use-map", action="store_true", default=False) + parser.add_option("--map-levels", type="int", default=4) + + parser.add_option("--recycle-latency", type="int", default=10, + help="Recycle latency for ruby controller input buffers") + + parser.add_option("--random_seed", type="int", default=1234, + help="Used for seeding the random number generator") + + parser.add_option("--ruby_stats", type="string", default="ruby.stats") + + protocol = buildEnv['PROTOCOL'] + exec "import %s" % protocol + eval("%s.define_options(parser)" % protocol) + +def create_system(options, system, piobus = None, dma_ports = []): + + system.ruby = RubySystem(clock = options.clock, + stats_filename = options.ruby_stats, + no_mem_vec = options.use_map) + ruby = system.ruby + + protocol = buildEnv['PROTOCOL'] + exec "import %s" % protocol + try: + (cpu_sequencers, dir_cntrls, all_cntrls) = \ + eval("%s.create_system(options, system, piobus, dma_ports, ruby)" + % protocol) + except: + print "Error: could not create sytem for ruby protocol %s" % protocol + raise + + # Create a port proxy for connecting the system port. This is + # independent of the protocol and kept in the protocol-agnostic + # part (i.e. here). + sys_port_proxy = RubyPortProxy(ruby_system = ruby) + # Give the system port proxy a SimObject parent without creating a + # full-fledged controller + system.sys_port_proxy = sys_port_proxy + + # Connect the system port for loading of binaries etc + system.system_port = system.sys_port_proxy.slave + + + # + # Set the network classes based on the command line options + # + if options.garnet_network == "fixed": + class NetworkClass(GarnetNetwork_d): pass + class IntLinkClass(GarnetIntLink_d): pass + class ExtLinkClass(GarnetExtLink_d): pass + class RouterClass(GarnetRouter_d): pass + elif options.garnet_network == "flexible": + class NetworkClass(GarnetNetwork): pass + class IntLinkClass(GarnetIntLink): pass + class ExtLinkClass(GarnetExtLink): pass + class RouterClass(GarnetRouter): pass + else: + class NetworkClass(SimpleNetwork): pass + class IntLinkClass(SimpleIntLink): pass + class ExtLinkClass(SimpleExtLink): pass + class RouterClass(BasicRouter): pass + + # + # Important: the topology must be created before the network and after the + # controllers. + # + exec "import %s" % options.topology + try: + net_topology = eval("%s.makeTopology(all_cntrls, options, \ + IntLinkClass, ExtLinkClass, \ + RouterClass)" \ + % options.topology) + except: + print "Error: could not create topology %s" % options.topology + raise + + if options.network_fault_model: + assert(options.garnet_network == "fixed") + fault_model = FaultModel() + network = NetworkClass(ruby_system = ruby, topology = net_topology,\ + enable_fault_model=True, fault_model = fault_model) + else: + network = NetworkClass(ruby_system = ruby, topology = net_topology) + + # + # Loop through the directory controlers. + # Determine the total memory size of the ruby system and verify it is equal + # to physmem. However, if Ruby memory is using sparse memory in SE + # mode, then the system should not back-up the memory state with + # the Memory Vector and thus the memory size bytes should stay at 0. + # Also set the numa bits to the appropriate values. + # + total_mem_size = MemorySize('0B') + + dir_bits = int(math.log(options.num_dirs, 2)) + + if options.numa_high_bit: + numa_bit = options.numa_high_bit + else: + # if not specified, use the lowest bits above the block offest + if dir_bits > 0: + # add 5 because bits 0-5 are the block offset + numa_bit = dir_bits + 5 + else: + numa_bit = 6 + + for dir_cntrl in dir_cntrls: + total_mem_size.value += dir_cntrl.directory.size.value + dir_cntrl.directory.numa_high_bit = numa_bit + + phys_mem_size = 0 + for mem in system.memories.unproxy(system): + phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1 + assert(total_mem_size.value == phys_mem_size) + + ruby_profiler = RubyProfiler(ruby_system = ruby, + num_of_sequencers = len(cpu_sequencers)) + ruby.network = network + ruby.profiler = ruby_profiler + ruby.mem_size = total_mem_size + ruby._cpu_ruby_ports = cpu_sequencers + ruby.random_seed = options.random_seed diff --git a/simulators/gem5/configs/splash2/cluster.py b/simulators/gem5/configs/splash2/cluster.py new file mode 100644 index 00000000..d7e32a41 --- /dev/null +++ b/simulators/gem5/configs/splash2/cluster.py @@ -0,0 +1,304 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski + +# Simple test script +# +# "m5 test.py" + +import os +import optparse +import sys + +import m5 +from m5.objects import * + +m5.util.addToPath('../common') + +# -------------------- +# Define Command Line Options +# ==================== + +parser = optparse.OptionParser() + +parser.add_option("-d", "--detailed", action="store_true") +parser.add_option("-t", "--timing", action="store_true") +parser.add_option("-m", "--maxtick", type="int") +parser.add_option("-c", "--numclusters", + help="Number of clusters", type="int") +parser.add_option("-n", "--numcpus", + help="Number of cpus in total", type="int") +parser.add_option("-f", "--frequency", + default = "1GHz", + help="Frequency of each CPU") +parser.add_option("--l1size", + default = "32kB") +parser.add_option("--l1latency", + default = 1) +parser.add_option("--l2size", + default = "256kB") +parser.add_option("--l2latency", + default = 10) +parser.add_option("--rootdir", + help="ROot directory of Splash2", + default="/dist/splash2/codes/") +parser.add_option("-b", "--benchmark", + help="Splash 2 benchmark to run") + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +# -------------------- +# Define Splash2 Benchmarks +# ==================== +class Cholesky(LiveProcess): + executable = options.rootdir + '/kernels/cholesky/CHOLESKY' + cmd = 'CHOLESKY -p' + str(options.numcpus) + ' '\ + + options.rootdir + '/kernels/cholesky/inputs/tk23.O' + +class FFT(LiveProcess): + executable = options.rootdir + 'kernels/fft/FFT' + cmd = 'FFT -p' + str(options.numcpus) + ' -m18' + +class LU_contig(LiveProcess): + executable = options.rootdir + 'kernels/lu/contiguous_blocks/LU' + cmd = 'LU -p' + str(options.numcpus) + +class LU_noncontig(LiveProcess): + executable = options.rootdir + 'kernels/lu/non_contiguous_blocks/LU' + cmd = 'LU -p' + str(options.numcpus) + +class Radix(LiveProcess): + executable = options.rootdir + 'kernels/radix/RADIX' + cmd = 'RADIX -n524288 -p' + str(options.numcpus) + +class Barnes(LiveProcess): + executable = options.rootdir + 'apps/barnes/BARNES' + cmd = 'BARNES' + input = options.rootdir + 'apps/barnes/input.p' + str(options.numcpus) + +class FMM(LiveProcess): + executable = options.rootdir + 'apps/fmm/FMM' + cmd = 'FMM' + input = options.rootdir + 'apps/fmm/inputs/input.2048.p' + str(options.numcpus) + +class Ocean_contig(LiveProcess): + executable = options.rootdir + 'apps/ocean/contiguous_partitions/OCEAN' + cmd = 'OCEAN -p' + str(options.numcpus) + +class Ocean_noncontig(LiveProcess): + executable = options.rootdir + 'apps/ocean/non_contiguous_partitions/OCEAN' + cmd = 'OCEAN -p' + str(options.numcpus) + +class Raytrace(LiveProcess): + executable = options.rootdir + 'apps/raytrace/RAYTRACE' + cmd = 'RAYTRACE -p' + str(options.numcpus) + ' ' \ + + options.rootdir + 'apps/raytrace/inputs/teapot.env' + +class Water_nsquared(LiveProcess): + executable = options.rootdir + 'apps/water-nsquared/WATER-NSQUARED' + cmd = 'WATER-NSQUARED' + input = options.rootdir + 'apps/water-nsquared/input.p' + str(options.numcpus) + +class Water_spatial(LiveProcess): + executable = options.rootdir + 'apps/water-spatial/WATER-SPATIAL' + cmd = 'WATER-SPATIAL' + input = options.rootdir + 'apps/water-spatial/input.p' + str(options.numcpus) + + +# -------------------- +# Base L1 Cache Definition +# ==================== + +class L1(BaseCache): + latency = options.l1latency + block_size = 64 + mshrs = 12 + tgts_per_mshr = 8 + +# ---------------------- +# Base L2 Cache Definition +# ---------------------- + +class L2(BaseCache): + block_size = 64 + latency = options.l2latency + mshrs = 92 + tgts_per_mshr = 16 + write_buffers = 8 + +# ---------------------- +# Define the clusters with their cpus +# ---------------------- +class Cluster: + pass + +cpusPerCluster = options.numcpus/options.numclusters + +busFrequency = Frequency(options.frequency) +busFrequency *= cpusPerCluster + +all_cpus = [] +all_l1s = [] +all_l1buses = [] +if options.timing: + clusters = [ Cluster() for i in xrange(options.numclusters)] + for j in xrange(options.numclusters): + clusters[j].id = j + for cluster in clusters: + cluster.clusterbus = CoherentBus(clock=busFrequency) + all_l1buses += [cluster.clusterbus] + cluster.cpus = [TimingSimpleCPU(cpu_id = i + cluster.id, + clock=options.frequency) + for i in xrange(cpusPerCluster)] + all_cpus += cluster.cpus + cluster.l1 = L1(size=options.l1size, assoc = 4) + all_l1s += [cluster.l1] +elif options.detailed: + clusters = [ Cluster() for i in xrange(options.numclusters)] + for j in xrange(options.numclusters): + clusters[j].id = j + for cluster in clusters: + cluster.clusterbus = CoherentBus(clock=busFrequency) + all_l1buses += [cluster.clusterbus] + cluster.cpus = [DerivO3CPU(cpu_id = i + cluster.id, + clock=options.frequency) + for i in xrange(cpusPerCluster)] + all_cpus += cluster.cpus + cluster.l1 = L1(size=options.l1size, assoc = 4) + all_l1s += [cluster.l1] +else: + clusters = [ Cluster() for i in xrange(options.numclusters)] + for j in xrange(options.numclusters): + clusters[j].id = j + for cluster in clusters: + cluster.clusterbus = CoherentBus(clock=busFrequency) + all_l1buses += [cluster.clusterbus] + cluster.cpus = [AtomicSimpleCPU(cpu_id = i + cluster.id, + clock=options.frequency) + for i in xrange(cpusPerCluster)] + all_cpus += cluster.cpus + cluster.l1 = L1(size=options.l1size, assoc = 4) + all_l1s += [cluster.l1] + +# ---------------------- +# Create a system, and add system wide objects +# ---------------------- +system = System(cpu = all_cpus, l1_ = all_l1s, l1bus_ = all_l1buses, + physmem = SimpleMemory(), + membus = CoherentBus(clock = busFrequency)) + +system.toL2bus = CoherentBus(clock = busFrequency) +system.l2 = L2(size = options.l2size, assoc = 8) + +# ---------------------- +# Connect the L2 cache and memory together +# ---------------------- + +system.physmem.port = system.membus.master +system.l2.cpu_side = system.toL2bus.slave +system.l2.mem_side = system.membus.master + +# ---------------------- +# Connect the L2 cache and clusters together +# ---------------------- +for cluster in clusters: + cluster.l1.cpu_side = cluster.clusterbus.master + cluster.l1.mem_side = system.toL2bus.slave + for cpu in cluster.cpus: + cpu.icache_port = cluster.clusterbus.slave + cpu.dcache_port = cluster.clusterbus.slave + +# ---------------------- +# Define the root +# ---------------------- + +root = Root(full_system = False, system = system) + +# -------------------- +# Pick the correct Splash2 Benchmarks +# ==================== +if options.benchmark == 'Cholesky': + root.workload = Cholesky() +elif options.benchmark == 'FFT': + root.workload = FFT() +elif options.benchmark == 'LUContig': + root.workload = LU_contig() +elif options.benchmark == 'LUNoncontig': + root.workload = LU_noncontig() +elif options.benchmark == 'Radix': + root.workload = Radix() +elif options.benchmark == 'Barnes': + root.workload = Barnes() +elif options.benchmark == 'FMM': + root.workload = FMM() +elif options.benchmark == 'OceanContig': + root.workload = Ocean_contig() +elif options.benchmark == 'OceanNoncontig': + root.workload = Ocean_noncontig() +elif options.benchmark == 'Raytrace': + root.workload = Raytrace() +elif options.benchmark == 'WaterNSquared': + root.workload = Water_nsquared() +elif options.benchmark == 'WaterSpatial': + root.workload = Water_spatial() +else: + m5.util.panic(""" +The --benchmark environment variable was set to something improper. +Use Cholesky, FFT, LUContig, LUNoncontig, Radix, Barnes, FMM, OceanContig, +OceanNoncontig, Raytrace, WaterNSquared, or WaterSpatial +""") + +# -------------------- +# Assign the workload to the cpus +# ==================== + +for cluster in clusters: + for cpu in cluster.cpus: + cpu.workload = root.workload + +# ---------------------- +# Run the simulation +# ---------------------- + +if options.timing or options.detailed: + root.system.mem_mode = 'timing' + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +if options.maxtick: + exit_event = m5.simulate(options.maxtick) +else: + exit_event = m5.simulate(m5.MaxTick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() + diff --git a/simulators/gem5/configs/splash2/run.py b/simulators/gem5/configs/splash2/run.py new file mode 100644 index 00000000..48e255c5 --- /dev/null +++ b/simulators/gem5/configs/splash2/run.py @@ -0,0 +1,288 @@ +# Copyright (c) 2005-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ron Dreslinski + +# Splash2 Run Script +# + +import os +import optparse +import sys + +import m5 +from m5.objects import * + +m5.util.addToPath('../common') + +# -------------------- +# Define Command Line Options +# ==================== + +parser = optparse.OptionParser() + +parser.add_option("-d", "--detailed", action="store_true") +parser.add_option("-t", "--timing", action="store_true") +parser.add_option("-m", "--maxtick", type="int") +parser.add_option("-n", "--numcpus", + help="Number of cpus in total", type="int") +parser.add_option("-f", "--frequency", + default = "1GHz", + help="Frequency of each CPU") +parser.add_option("--l1size", + default = "32kB") +parser.add_option("--l1latency", + default = "1ns") +parser.add_option("--l2size", + default = "256kB") +parser.add_option("--l2latency", + default = "10ns") +parser.add_option("--rootdir", + help="Root directory of Splash2", + default="/dist/splash2/codes") +parser.add_option("-b", "--benchmark", + help="Splash 2 benchmark to run") + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +if not options.numcpus: + print "Specify the number of cpus with -n" + sys.exit(1) + +# -------------------- +# Define Splash2 Benchmarks +# ==================== +class Cholesky(LiveProcess): + cwd = options.rootdir + '/kernels/cholesky' + executable = options.rootdir + '/kernels/cholesky/CHOLESKY' + cmd = ['CHOLESKY', '-p' + str(options.numcpus), + options.rootdir + '/kernels/cholesky/inputs/tk23.O'] + +class FFT(LiveProcess): + cwd = options.rootdir + '/kernels/fft' + executable = options.rootdir + '/kernels/fft/FFT' + cmd = ['FFT', '-p', str(options.numcpus), '-m18'] + +class LU_contig(LiveProcess): + executable = options.rootdir + '/kernels/lu/contiguous_blocks/LU' + cmd = ['LU', '-p', str(options.numcpus)] + cwd = options.rootdir + '/kernels/lu/contiguous_blocks' + +class LU_noncontig(LiveProcess): + executable = options.rootdir + '/kernels/lu/non_contiguous_blocks/LU' + cmd = ['LU', '-p', str(options.numcpus)] + cwd = options.rootdir + '/kernels/lu/non_contiguous_blocks' + +class Radix(LiveProcess): + executable = options.rootdir + '/kernels/radix/RADIX' + cmd = ['RADIX', '-n524288', '-p', str(options.numcpus)] + cwd = options.rootdir + '/kernels/radix' + +class Barnes(LiveProcess): + executable = options.rootdir + '/apps/barnes/BARNES' + cmd = ['BARNES'] + input = options.rootdir + '/apps/barnes/input.p' + str(options.numcpus) + cwd = options.rootdir + '/apps/barnes' + +class FMM(LiveProcess): + executable = options.rootdir + '/apps/fmm/FMM' + cmd = ['FMM'] + if str(options.numcpus) == '1': + input = options.rootdir + '/apps/fmm/inputs/input.2048' + else: + input = options.rootdir + '/apps/fmm/inputs/input.2048.p' + str(options.numcpus) + cwd = options.rootdir + '/apps/fmm' + +class Ocean_contig(LiveProcess): + executable = options.rootdir + '/apps/ocean/contiguous_partitions/OCEAN' + cmd = ['OCEAN', '-p', str(options.numcpus)] + cwd = options.rootdir + '/apps/ocean/contiguous_partitions' + +class Ocean_noncontig(LiveProcess): + executable = options.rootdir + '/apps/ocean/non_contiguous_partitions/OCEAN' + cmd = ['OCEAN', '-p', str(options.numcpus)] + cwd = options.rootdir + '/apps/ocean/non_contiguous_partitions' + +class Raytrace(LiveProcess): + executable = options.rootdir + '/apps/raytrace/RAYTRACE' + cmd = ['RAYTRACE', '-p' + str(options.numcpus), + options.rootdir + '/apps/raytrace/inputs/teapot.env'] + cwd = options.rootdir + '/apps/raytrace' + +class Water_nsquared(LiveProcess): + executable = options.rootdir + '/apps/water-nsquared/WATER-NSQUARED' + cmd = ['WATER-NSQUARED'] + if options.numcpus==1: + input = options.rootdir + '/apps/water-nsquared/input' + else: + input = options.rootdir + '/apps/water-nsquared/input.p' + str(options.numcpus) + cwd = options.rootdir + '/apps/water-nsquared' + +class Water_spatial(LiveProcess): + executable = options.rootdir + '/apps/water-spatial/WATER-SPATIAL' + cmd = ['WATER-SPATIAL'] + if options.numcpus==1: + input = options.rootdir + '/apps/water-spatial/input' + else: + input = options.rootdir + '/apps/water-spatial/input.p' + str(options.numcpus) + cwd = options.rootdir + '/apps/water-spatial' + +# -------------------- +# Base L1 Cache Definition +# ==================== + +class L1(BaseCache): + latency = options.l1latency + block_size = 64 + mshrs = 12 + tgts_per_mshr = 8 + +# ---------------------- +# Base L2 Cache Definition +# ---------------------- + +class L2(BaseCache): + block_size = 64 + latency = options.l2latency + mshrs = 92 + tgts_per_mshr = 16 + write_buffers = 8 + +# ---------------------- +# Define the cpus +# ---------------------- + +busFrequency = Frequency(options.frequency) + +if options.timing: + cpus = [TimingSimpleCPU(cpu_id = i, + clock=options.frequency) + for i in xrange(options.numcpus)] +elif options.detailed: + cpus = [DerivO3CPU(cpu_id = i, + clock=options.frequency) + for i in xrange(options.numcpus)] +else: + cpus = [AtomicSimpleCPU(cpu_id = i, + clock=options.frequency) + for i in xrange(options.numcpus)] + +# ---------------------- +# Create a system, and add system wide objects +# ---------------------- +system = System(cpu = cpus, physmem = SimpleMemory(), + membus = CoherentBus(clock = busFrequency)) + +system.toL2bus = CoherentBus(clock = busFrequency) +system.l2 = L2(size = options.l2size, assoc = 8) + +# ---------------------- +# Connect the L2 cache and memory together +# ---------------------- + +system.physmem.port = system.membus.master +system.l2.cpu_side = system.toL2bus.master +system.l2.mem_side = system.membus.slave +system.system_port = system.membus.slave + +# ---------------------- +# Connect the L2 cache and clusters together +# ---------------------- +for cpu in cpus: + cpu.addPrivateSplitL1Caches(L1(size = options.l1size, assoc = 1), + L1(size = options.l1size, assoc = 4)) + # connect cpu level-1 caches to shared level-2 cache + cpu.connectAllPorts(system.toL2bus, system.membus) + + +# ---------------------- +# Define the root +# ---------------------- + +root = Root(full_system = False, system = system) + +# -------------------- +# Pick the correct Splash2 Benchmarks +# ==================== +if options.benchmark == 'Cholesky': + root.workload = Cholesky() +elif options.benchmark == 'FFT': + root.workload = FFT() +elif options.benchmark == 'LUContig': + root.workload = LU_contig() +elif options.benchmark == 'LUNoncontig': + root.workload = LU_noncontig() +elif options.benchmark == 'Radix': + root.workload = Radix() +elif options.benchmark == 'Barnes': + root.workload = Barnes() +elif options.benchmark == 'FMM': + root.workload = FMM() +elif options.benchmark == 'OceanContig': + root.workload = Ocean_contig() +elif options.benchmark == 'OceanNoncontig': + root.workload = Ocean_noncontig() +elif options.benchmark == 'Raytrace': + root.workload = Raytrace() +elif options.benchmark == 'WaterNSquared': + root.workload = Water_nsquared() +elif options.benchmark == 'WaterSpatial': + root.workload = Water_spatial() +else: + print >> sys.stderr, """The --benchmark environment variable was set to something improper. +Use Cholesky, FFT, LUContig, LUNoncontig, Radix, Barnes, FMM, OceanContig, +OceanNoncontig, Raytrace, WaterNSquared, or WaterSpatial""" + sys.exit(1) + +# -------------------- +# Assign the workload to the cpus +# ==================== + +for cpu in cpus: + cpu.workload = root.workload + +# ---------------------- +# Run the simulation +# ---------------------- + +if options.timing or options.detailed: + root.system.mem_mode = 'timing' + +# instantiate configuration +m5.instantiate() + +# simulate until program terminates +if options.maxtick: + exit_event = m5.simulate(options.maxtick) +else: + exit_event = m5.simulate(m5.MaxTick) + +print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() + diff --git a/simulators/gem5/ext/dnet/LICENSE b/simulators/gem5/ext/dnet/LICENSE new file mode 100644 index 00000000..95ecd51e --- /dev/null +++ b/simulators/gem5/ext/dnet/LICENSE @@ -0,0 +1,28 @@ + + Copyright (c) 2000-2004 Dug Song + All rights reserved, all wrongs reversed. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The names of the authors and copyright holders may not be used to + endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/simulators/gem5/ext/dnet/addr.h b/simulators/gem5/ext/dnet/addr.h new file mode 100644 index 00000000..584e3aba --- /dev/null +++ b/simulators/gem5/ext/dnet/addr.h @@ -0,0 +1,67 @@ +/* + * addr.h + * + * Network address operations. + * + * Copyright (c) 2000 Dug Song + * + * $Id: addr.h,v 1.12 2003/02/27 03:44:55 dugsong Exp $ + */ + +#ifndef DNET_ADDR_H +#define DNET_ADDR_H + +#define ADDR_TYPE_NONE 0 /* No address set */ +#define ADDR_TYPE_ETH 1 /* Ethernet */ +#define ADDR_TYPE_IP 2 /* Internet Protocol v4 */ +#define ADDR_TYPE_IP6 3 /* Internet Protocol v6 */ + +struct addr { + uint16_t addr_type; + uint16_t addr_bits; + union { + eth_addr_t __eth; + ip_addr_t __ip; + ip6_addr_t __ip6; + + uint8_t __data8[16]; + uint16_t __data16[8]; + uint32_t __data32[4]; + } __addr_u; +}; +#define addr_eth __addr_u.__eth +#define addr_ip __addr_u.__ip +#define addr_ip6 __addr_u.__ip6 +#define addr_data8 __addr_u.__data8 +#define addr_data16 __addr_u.__data16 +#define addr_data32 __addr_u.__data32 + +#define addr_pack(addr, type, bits, data, len) do { \ + (addr)->addr_type = type; \ + (addr)->addr_bits = bits; \ + memmove((addr)->addr_data8, (char *)data, len); \ +} while (0) + +__BEGIN_DECLS +int addr_cmp(const struct addr *a, const struct addr *b); + +int addr_bcast(const struct addr *a, struct addr *b); +int addr_net(const struct addr *a, struct addr *b); + +char *addr_ntop(const struct addr *src, char *dst, size_t size); +int addr_pton(const char *src, struct addr *dst); + +char *addr_ntoa(const struct addr *a); +#define addr_aton addr_pton + +int addr_ntos(const struct addr *a, struct sockaddr *sa); +int addr_ston(const struct sockaddr *sa, struct addr *a); + +int addr_btos(uint16_t bits, struct sockaddr *sa); +int addr_stob(const struct sockaddr *sa, uint16_t *bits); + +int addr_btom(uint16_t bits, void *mask, size_t size); +int addr_mtob(const void *mask, size_t size, uint16_t *bits); +__END_DECLS + +#endif /* DNET_ADDR_H */ diff --git a/simulators/gem5/ext/dnet/arp.h b/simulators/gem5/ext/dnet/arp.h new file mode 100644 index 00000000..d3c16241 --- /dev/null +++ b/simulators/gem5/ext/dnet/arp.h @@ -0,0 +1,103 @@ +/* + * arp.h + * + * Address Resolution Protocol. + * RFC 826 + * + * Copyright (c) 2000 Dug Song + * + * $Id: arp.h,v 1.12 2003/03/16 17:39:17 dugsong Exp $ + */ + +#ifndef DNET_ARP_H +#define DNET_ARP_H + +#define ARP_HDR_LEN 8 /* base ARP header length */ +#define ARP_ETHIP_LEN 20 /* base ARP message length */ + +#ifndef __GNUC__ +# define __attribute__(x) +# pragma pack(1) +#endif + +/* + * ARP header + */ +struct arp_hdr { + uint16_t ar_hrd; /* format of hardware address */ + uint16_t ar_pro; /* format of protocol address */ + uint8_t ar_hln; /* length of hardware address (ETH_ADDR_LEN) */ + uint8_t ar_pln; /* length of protocol address (IP_ADDR_LEN) */ + uint16_t ar_op; /* operation */ +}; + +/* + * Hardware address format + */ +#define ARP_HRD_ETH 0x0001 /* ethernet hardware */ +#define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */ + +/* + * Protocol address format + */ +#define ARP_PRO_IP 0x0800 /* IP protocol */ + +/* + * ARP operation + */ +#define ARP_OP_REQUEST 1 /* request to resolve ha given pa */ +#define ARP_OP_REPLY 2 /* response giving hardware address */ +#define ARP_OP_REVREQUEST 3 /* request to resolve pa given ha */ +#define ARP_OP_REVREPLY 4 /* response giving protocol address */ + +/* + * Ethernet/IP ARP message + */ +struct arp_ethip { + uint8_t ar_sha[ETH_ADDR_LEN]; /* sender hardware address */ + uint8_t ar_spa[IP_ADDR_LEN]; /* sender protocol address */ + uint8_t ar_tha[ETH_ADDR_LEN]; /* target hardware address */ + uint8_t ar_tpa[IP_ADDR_LEN]; /* target protocol address */ +}; + +/* + * ARP cache entry + */ +struct arp_entry { + struct addr arp_pa; /* protocol address */ + struct addr arp_ha; /* hardware address */ +}; + +#ifndef __GNUC__ +# pragma pack() +#endif + +#define arp_pack_hdr_ethip(hdr, op, sha, spa, tha, tpa) do { \ + struct arp_hdr *pack_arp_p = (struct arp_hdr *)(hdr); \ + struct arp_ethip *pack_ethip_p = (struct arp_ethip *) \ + ((uint8_t *)(hdr) + ARP_HDR_LEN); \ + pack_arp_p->ar_hrd = htons(ARP_HRD_ETH); \ + pack_arp_p->ar_pro = htons(ARP_PRO_IP); \ + pack_arp_p->ar_hln = ETH_ADDR_LEN; \ + pack_arp_p->ar_pln = IP_ADDR_LEN; \ + pack_arp_p->ar_op = htons(op); \ + memmove(pack_ethip_p->ar_sha, &(sha), ETH_ADDR_LEN); \ + memmove(pack_ethip_p->ar_spa, &(spa), IP_ADDR_LEN); \ + memmove(pack_ethip_p->ar_tha, &(tha), ETH_ADDR_LEN); \ + memmove(pack_ethip_p->ar_tpa, &(tpa), IP_ADDR_LEN); \ +} while (0) + +typedef struct arp_handle arp_t; + +typedef int (*arp_handler)(const struct arp_entry *entry, void *arg); + +__BEGIN_DECLS +arp_t *arp_open(void); +int arp_add(arp_t *arp, const struct arp_entry *entry); +int arp_delete(arp_t *arp, const struct arp_entry *entry); +int arp_get(arp_t *arp, struct arp_entry *entry); +int arp_loop(arp_t *arp, arp_handler callback, void *arg); +arp_t *arp_close(arp_t *arp); +__END_DECLS + +#endif /* DNET_ARP_H */ diff --git a/simulators/gem5/ext/dnet/blob.h b/simulators/gem5/ext/dnet/blob.h new file mode 100644 index 00000000..a3be7897 --- /dev/null +++ b/simulators/gem5/ext/dnet/blob.h @@ -0,0 +1,56 @@ +/* + * blob.h + * + * Binary blob handling. + * + * Copyright (c) 2002 Dug Song + * + * $Id: blob.h,v 1.2 2002/04/05 03:06:44 dugsong Exp $ + */ + +#ifndef DNET_BLOB_H +#define DNET_BLOB_H + +typedef struct blob { + u_char *base; /* start of data */ + int off; /* offset into data */ + int end; /* end of data */ + int size; /* size of allocation */ +} blob_t; + +__BEGIN_DECLS +blob_t *blob_new(void); + +int blob_read(blob_t *b, void *buf, int len); +int blob_write(blob_t *b, const void *buf, int len); + +int blob_seek(blob_t *b, int off, int whence); +#define blob_skip(b, l) blob_seek(b, l, SEEK_CUR) +#define blob_rewind(b) blob_seek(b, 0, SEEK_SET) + +#define blob_offset(b) ((b)->off) +#define blob_left(b) ((b)->end - (b)->off) + +int blob_index(blob_t *b, const void *buf, int len); +int blob_rindex(blob_t *b, const void *buf, int len); + +int blob_pack(blob_t *b, const char *fmt, ...); +int blob_unpack(blob_t *b, const char *fmt, ...); + +int blob_insert(blob_t *b, const void *buf, int len); +int blob_delete(blob_t *b, void *buf, int len); + +int blob_print(blob_t *b, char *style, int len); + +blob_t *blob_free(blob_t *b); + +int blob_register_alloc(size_t size, void *(*bmalloc)(size_t), + void (*bfree)(void *), void *(*brealloc)(void *, size_t)); +#ifdef va_start +typedef int (*blob_fmt_cb)(int pack, int len, blob_t *b, va_list *arg); + +int blob_register_pack(char c, blob_fmt_cb fmt_cb); +#endif +__END_DECLS + +#endif /* DNET_BLOB_H */ diff --git a/simulators/gem5/ext/dnet/eth.h b/simulators/gem5/ext/dnet/eth.h new file mode 100644 index 00000000..da303306 --- /dev/null +++ b/simulators/gem5/ext/dnet/eth.h @@ -0,0 +1,77 @@ +/* + * eth.h + * + * Ethernet. + * + * Copyright (c) 2000 Dug Song + * + * $Id: eth.h,v 1.15 2004/01/03 08:47:23 dugsong Exp $ + */ + +#ifndef DNET_ETH_H +#define DNET_ETH_H + +#define ETH_ADDR_LEN 6 +#define ETH_ADDR_BITS 48 +#define ETH_TYPE_LEN 2 +#define ETH_CRC_LEN 4 +#define ETH_HDR_LEN 14 + +#define ETH_LEN_MIN 64 /* minimum frame length with CRC */ +#define ETH_LEN_MAX 1518 /* maximum frame length with CRC */ + +#define ETH_MTU (ETH_LEN_MAX - ETH_HDR_LEN - ETH_CRC_LEN) +#define ETH_MIN (ETH_LEN_MIN - ETH_HDR_LEN - ETH_CRC_LEN) + +typedef struct eth_addr { + uint8_t data[ETH_ADDR_LEN]; +} eth_addr_t; + +struct eth_hdr { + eth_addr_t eth_dst; /* destination address */ + eth_addr_t eth_src; /* source address */ + uint16_t eth_type; /* payload type */ +}; + +/* + * Ethernet payload types - http://standards.ieee.org/regauth/ethertype + */ +#define ETH_TYPE_PUP 0x0200 /* PUP protocol */ +#define ETH_TYPE_IP 0x0800 /* IP protocol */ +#define ETH_TYPE_ARP 0x0806 /* address resolution protocol */ +#define ETH_TYPE_REVARP 0x8035 /* reverse addr resolution protocol */ +#define ETH_TYPE_8021Q 0x8100 /* IEEE 802.1Q VLAN tagging */ +#define ETH_TYPE_IPV6 0x86DD /* IPv6 protocol */ +#define ETH_TYPE_MPLS 0x8847 /* MPLS */ +#define ETH_TYPE_MPLS_MCAST 0x8848 /* MPLS Multicast */ +#define ETH_TYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */ +#define ETH_TYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */ +#define ETH_TYPE_LOOPBACK 0x9000 /* used to test interfaces */ + +#define ETH_IS_MULTICAST(ea) (*(ea) & 0x01) /* is address mcast/bcast? */ + +#define ETH_ADDR_BROADCAST "\xff\xff\xff\xff\xff\xff" + +#define eth_pack_hdr(h, dst, src, type) do { \ + struct eth_hdr *eth_pack_p = (struct eth_hdr *)(h); \ + memmove(ð_pack_p->eth_dst, &(dst), ETH_ADDR_LEN); \ + memmove(ð_pack_p->eth_src, &(src), ETH_ADDR_LEN); \ + eth_pack_p->eth_type = htons(type); \ +} while (0) + +typedef struct eth_handle eth_t; + +__BEGIN_DECLS +eth_t *eth_open(const char *device); +int eth_get(eth_t *e, eth_addr_t *ea); +int eth_set(eth_t *e, const eth_addr_t *ea); +size_t eth_send(eth_t *e, const void *buf, size_t len); +eth_t *eth_close(eth_t *e); + +char *eth_ntop(const eth_addr_t *eth, char *dst, size_t len); +int eth_pton(const char *src, eth_addr_t *dst); +char *eth_ntoa(const eth_addr_t *eth); +#define eth_aton eth_pton +__END_DECLS + +#endif /* DNET_ETH_H */ diff --git a/simulators/gem5/ext/dnet/fw.h b/simulators/gem5/ext/dnet/fw.h new file mode 100644 index 00000000..ebda8e7e --- /dev/null +++ b/simulators/gem5/ext/dnet/fw.h @@ -0,0 +1,54 @@ +/* + * fw.h + * + * Network firewalling operations. + * + * Copyright (c) 2001 Dug Song + * + * $Id: fw.h,v 1.13 2002/12/14 04:02:36 dugsong Exp $ + */ + +#ifndef DNET_FW_H +#define DNET_FW_H + +struct fw_rule { + char fw_device[INTF_NAME_LEN]; /* interface name */ + uint8_t fw_op; /* operation */ + uint8_t fw_dir; /* direction */ + uint8_t fw_proto; /* IP protocol */ + struct addr fw_src; /* src address / net */ + struct addr fw_dst; /* dst address / net */ + uint16_t fw_sport[2]; /* range / ICMP type */ + uint16_t fw_dport[2]; /* range / ICMP code */ +}; + +#define FW_OP_ALLOW 1 +#define FW_OP_BLOCK 2 + +#define FW_DIR_IN 1 +#define FW_DIR_OUT 2 + +#define fw_pack_rule(rule, dev, op, dir, p, s, d, sp1, sp2, dp1, dp2) \ +do { \ + strlcpy((rule)->fw_device, dev, sizeof((rule)->fw_device)); \ + (rule)->fw_op = op; (rule)->fw_dir = dir; \ + (rule)->fw_proto = p; \ + memmove(&(rule)->fw_src, &(s), sizeof((rule)->fw_src)); \ + memmove(&(rule)->fw_dst, &(d), sizeof((rule)->fw_dst)); \ + (rule)->fw_sport[0] = sp1; (rule)->fw_sport[1] = sp2; \ + (rule)->fw_dport[0] = dp1; (rule)->fw_dport[1] = dp2; \ +} while (0) + +typedef struct fw_handle fw_t; + +typedef int (*fw_handler)(const struct fw_rule *rule, void *arg); + +__BEGIN_DECLS +fw_t *fw_open(void); +int fw_add(fw_t *f, const struct fw_rule *rule); +int fw_delete(fw_t *f, const struct fw_rule *rule); +int fw_loop(fw_t *f, fw_handler callback, void *arg); +fw_t *fw_close(fw_t *f); +__END_DECLS + +#endif /* DNET_FW_H */ diff --git a/simulators/gem5/ext/dnet/icmp.h b/simulators/gem5/ext/dnet/icmp.h new file mode 100644 index 00000000..e997d588 --- /dev/null +++ b/simulators/gem5/ext/dnet/icmp.h @@ -0,0 +1,265 @@ +/* + * icmp.h + * + * Internet Control Message Protocol. + * RFC 792, 950, 1256, 1393, 1475, 2002, 2521 + * + * Copyright (c) 2000 Dug Song + * + * $Id: icmp.h,v 1.14 2003/03/16 17:39:17 dugsong Exp $ + */ + +#ifndef DNET_ICMP_H +#define DNET_ICMP_H + +#define ICMP_HDR_LEN 4 /* base ICMP header length */ +#define ICMP_LEN_MIN 8 /* minimum ICMP message size, with header */ + +#ifndef __GNUC__ +# define __attribute__(x) +# pragma pack(1) +#endif + +/* + * ICMP header + */ +struct icmp_hdr { + uint8_t icmp_type; /* type of message, see below */ + uint8_t icmp_code; /* type sub code */ + uint16_t icmp_cksum; /* ones complement cksum of struct */ +}; + +/* + * Types (icmp_type) and codes (icmp_code) - + * http://www.iana.org/assignments/icmp-parameters + */ +#define ICMP_CODE_NONE 0 /* for types without codes */ +#define ICMP_ECHOREPLY 0 /* echo reply */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTO 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* for crypto devs */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* prohibited access */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* precedence error */ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ +#define ICMP_SRCQUENCH 4 /* packet lost, slow down */ +#define ICMP_REDIRECT 5 /* shorter route, codes: */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_ALTHOSTADDR 6 /* alternate host address */ +#define ICMP_ECHO 8 /* echo service */ +#define ICMP_RTRADVERT 9 /* router advertise, codes: */ +#define ICMP_RTRADVERT_NORMAL 0 /* normal */ +#define ICMP_RTRADVERT_NOROUTE_COMMON 16 /* selective routing */ +#define ICMP_RTRSOLICIT 10 /* router solicitation */ +#define ICMP_TIMEXCEED 11 /* time exceeded, code: */ +#define ICMP_TIMEXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMEXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_ERRATPTR 0 /* req. opt. absent */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ +#define ICMP_PARAMPROB_LENGTH 2 /* bad length */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_INFO 15 /* information request */ +#define ICMP_INFOREPLY 16 /* information reply */ +#define ICMP_MASK 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ +#define ICMP_TRACEROUTE 30 /* traceroute */ +#define ICMP_DATACONVERR 31 /* data conversion error */ +#define ICMP_MOBILE_REDIRECT 32 /* mobile host redirect */ +#define ICMP_IPV6_WHEREAREYOU 33 /* IPv6 where-are-you */ +#define ICMP_IPV6_IAMHERE 34 /* IPv6 i-am-here */ +#define ICMP_MOBILE_REG 35 /* mobile registration req */ +#define ICMP_MOBILE_REGREPLY 36 /* mobile registration reply */ +#define ICMP_DNS 37 /* domain name request */ +#define ICMP_DNSREPLY 38 /* domain name reply */ +#define ICMP_SKIP 39 /* SKIP */ +#define ICMP_PHOTURIS 40 /* Photuris */ +#define ICMP_PHOTURIS_UNKNOWN_INDEX 0 /* unknown sec index */ +#define ICMP_PHOTURIS_AUTH_FAILED 1 /* auth failed */ +#define ICMP_PHOTURIS_DECOMPRESS_FAILED 2 /* decompress failed */ +#define ICMP_PHOTURIS_DECRYPT_FAILED 3 /* decrypt failed */ +#define ICMP_PHOTURIS_NEED_AUTHN 4 /* no authentication */ +#define ICMP_PHOTURIS_NEED_AUTHZ 5 /* no authorization */ +#define ICMP_TYPE_MAX 40 + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_RTRADVERT || (type) == ICMP_RTRSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_INFO || (type) == ICMP_INFOREPLY || \ + (type) == ICMP_MASK || (type) == ICMP_MASKREPLY) + +/* + * Echo message data + */ +struct icmp_msg_echo { + uint16_t icmp_id; + uint16_t icmp_seq; + uint8_t icmp_data __flexarr; /* optional data */ +}; + +/* + * Fragmentation-needed (unreachable) message data + */ +struct icmp_msg_needfrag { + uint16_t icmp_void; /* must be zero */ + uint16_t icmp_mtu; /* MTU of next-hop network */ + uint8_t icmp_ip __flexarr; /* IP hdr + 8 bytes of pkt */ +}; + +/* + * Unreachable, source quench, redirect, time exceeded, + * parameter problem message data + */ +struct icmp_msg_quote { + uint32_t icmp_void; /* must be zero */ +#define icmp_gwaddr icmp_void /* router IP address to use */ +#define icmp_pptr icmp_void /* ptr to bad octet field */ + uint8_t icmp_ip __flexarr; /* IP hdr + 8 bytes of pkt */ +}; + +/* + * Router advertisement message data, RFC 1256 + */ +struct icmp_msg_rtradvert { + uint8_t icmp_num_addrs; /* # of address / pref pairs */ + uint8_t icmp_wpa; /* words / address == 2 */ + uint16_t icmp_lifetime; /* route lifetime in seconds */ + struct icmp_msg_rtr_data { + uint32_t icmp_void; +#define icmp_gwaddr icmp_void /* router IP address */ + uint32_t icmp_pref; /* router preference (usu 0) */ + } icmp_rtr __flexarr; /* variable # of routers */ +}; +#define ICMP_RTR_PREF_NODEFAULT 0x80000000 /* do not use as default gw */ + +/* + * Timestamp message data + */ +struct icmp_msg_tstamp { + uint32_t icmp_id; /* identifier */ + uint32_t icmp_seq; /* sequence number */ + uint32_t icmp_ts_orig; /* originate timestamp */ + uint32_t icmp_ts_rx; /* receive timestamp */ + uint32_t icmp_ts_tx; /* transmit timestamp */ +}; + +/* + * Address mask message data, RFC 950 + */ +struct icmp_msg_mask { + uint32_t icmp_id; /* identifier */ + uint32_t icmp_seq; /* sequence number */ + uint32_t icmp_mask; /* address mask */ +}; + +/* + * Traceroute message data, RFC 1393, RFC 1812 + */ +struct icmp_msg_traceroute { + uint16_t icmp_id; /* identifier */ + uint16_t icmp_void; /* unused */ + uint16_t icmp_ohc; /* outbound hop count */ + uint16_t icmp_rhc; /* return hop count */ + uint32_t icmp_speed; /* link speed, bytes/sec */ + uint32_t icmp_mtu; /* MTU in bytes */ +}; + +/* + * Domain name reply message data, RFC 1788 + */ +struct icmp_msg_dnsreply { + uint16_t icmp_id; /* identifier */ + uint16_t icmp_seq; /* sequence number */ + uint32_t icmp_ttl; /* time-to-live */ + uint8_t icmp_names __flexarr; /* variable number of names */ +}; + +/* + * Generic identifier, sequence number data + */ +struct icmp_msg_idseq { + uint16_t icmp_id; + uint16_t icmp_seq; +}; + +/* + * ICMP message union + */ +union icmp_msg { + struct icmp_msg_echo echo; /* ICMP_ECHO{REPLY} */ + struct icmp_msg_quote unreach; /* ICMP_UNREACH */ + struct icmp_msg_needfrag needfrag; /* ICMP_UNREACH_NEEDFRAG */ + struct icmp_msg_quote srcquench; /* ICMP_SRCQUENCH */ + struct icmp_msg_quote redirect; /* ICMP_REDIRECT (set to 0) */ + uint32_t rtrsolicit; /* ICMP_RTRSOLICIT */ + struct icmp_msg_rtradvert rtradvert; /* ICMP_RTRADVERT */ + struct icmp_msg_quote timexceed; /* ICMP_TIMEXCEED */ + struct icmp_msg_quote paramprob; /* ICMP_PARAMPROB */ + struct icmp_msg_tstamp tstamp; /* ICMP_TSTAMP{REPLY} */ + struct icmp_msg_idseq info; /* ICMP_INFO{REPLY} */ + struct icmp_msg_mask mask; /* ICMP_MASK{REPLY} */ + struct icmp_msg_traceroute traceroute; /* ICMP_TRACEROUTE */ + struct icmp_msg_idseq dns; /* ICMP_DNS */ + struct icmp_msg_dnsreply dnsreply; /* ICMP_DNSREPLY */ +}; + +#ifndef __GNUC__ +# pragma pack() +#endif + +#define icmp_pack_hdr(hdr, type, code) do { \ + struct icmp_hdr *icmp_pack_p = (struct icmp_hdr *)(hdr); \ + icmp_pack_p->icmp_type = type; icmp_pack_p->icmp_code = code; \ +} while (0) + +#define icmp_pack_hdr_echo(hdr, type, code, id, seq, data, len) do { \ + struct icmp_msg_echo *echo_pack_p = (struct icmp_msg_echo *) \ + ((uint8_t *)(hdr) + ICMP_HDR_LEN); \ + icmp_pack_hdr(hdr, type, code); \ + echo_pack_p->icmp_id = htons(id); \ + echo_pack_p->icmp_seq = htons(seq); \ + memmove(echo_pack_p->icmp_data, data, len); \ +} while (0) + +#define icmp_pack_hdr_quote(hdr, type, code, word, pkt, len) do { \ + struct icmp_msg_quote *quote_pack_p = (struct icmp_msg_quote *) \ + ((uint8_t *)(hdr) + ICMP_HDR_LEN); \ + icmp_pack_hdr(hdr, type, code); \ + quote_pack_p->icmp_void = htonl(word); \ + memmove(quote_pack_p->icmp_ip, pkt, len); \ +} while (0) + +#define icmp_pack_hdr_mask(hdr, type, code, id, seq, mask) do { \ + struct icmp_msg_mask *mask_pack_p = (struct icmp_msg_mask *) \ + ((uint8_t *)(hdr) + ICMP_HDR_LEN); \ + icmp_pack_hdr(hdr, type, code); \ + mask_pack_p->icmp_id = htons(id); \ + mask_pack_p->icmp_seq = htons(seq); \ + mask_pack_p->icmp_mask = htonl(mask); \ +} while (0) + +#define icmp_pack_hdr_needfrag(hdr, type, code, mtu, pkt, len) do { \ + struct icmp_msg_needfrag *frag_pack_p = \ + (struct icmp_msg_needfrag *)((uint8_t *)(hdr) + ICMP_HDR_LEN); \ + icmp_pack_hdr(hdr, type, code); \ + frag_pack_p->icmp_void = 0; \ + frag_pack_p->icmp_mtu = htons(mtu); \ + memmove(frag_pack_p->icmp_ip, pkt, len); \ +} while (0) + +#endif /* DNET_ICMP_H */ diff --git a/simulators/gem5/ext/dnet/intf.h b/simulators/gem5/ext/dnet/intf.h new file mode 100644 index 00000000..38acd435 --- /dev/null +++ b/simulators/gem5/ext/dnet/intf.h @@ -0,0 +1,68 @@ +/* + * intf.c + * + * Network interface operations. + * + * Copyright (c) 2000 Dug Song + * + * $Id: intf.h,v 1.16 2004/01/13 07:41:09 dugsong Exp $ + */ + +#ifndef DNET_INTF_H +#define DNET_INTF_H + +/* + * Interface entry + */ +#define INTF_NAME_LEN 16 + +struct intf_entry { + u_int intf_len; /* length of entry */ + char intf_name[INTF_NAME_LEN]; /* interface name */ + u_short intf_type; /* interface type (r/o) */ + u_short intf_flags; /* interface flags */ + u_int intf_mtu; /* interface MTU */ + struct addr intf_addr; /* interface address */ + struct addr intf_dst_addr; /* point-to-point dst */ + struct addr intf_link_addr; /* link-layer address */ + u_int intf_alias_num; /* number of aliases */ + struct addr intf_alias_addrs __flexarr; /* array of aliases */ +}; + +/* + * MIB-II interface types - http://www.iana.org/assignments/ianaiftype-mib + */ +#define INTF_TYPE_OTHER 1 /* other */ +#define INTF_TYPE_ETH 6 /* Ethernet */ +#define INTF_TYPE_TOKENRING 9 /* Token Ring */ +#define INTF_TYPE_FDDI 15 /* FDDI */ +#define INTF_TYPE_PPP 23 /* Point-to-Point Protocol */ +#define INTF_TYPE_LOOPBACK 24 /* software loopback */ +#define INTF_TYPE_SLIP 28 /* Serial Line Interface Protocol */ +#define INTF_TYPE_TUN 53 /* proprietary virtual/internal */ + +/* + * Interface flags + */ +#define INTF_FLAG_UP 0x01 /* enable interface */ +#define INTF_FLAG_LOOPBACK 0x02 /* is a loopback net (r/o) */ +#define INTF_FLAG_POINTOPOINT 0x04 /* point-to-point link (r/o) */ +#define INTF_FLAG_NOARP 0x08 /* disable ARP */ +#define INTF_FLAG_BROADCAST 0x10 /* supports broadcast (r/o) */ +#define INTF_FLAG_MULTICAST 0x20 /* supports multicast (r/o) */ + +typedef struct intf_handle intf_t; + +typedef int (*intf_handler)(const struct intf_entry *entry, void *arg); + +__BEGIN_DECLS +intf_t *intf_open(void); +int intf_get(intf_t *i, struct intf_entry *entry); +int intf_get_src(intf_t *i, struct intf_entry *entry, struct addr *src); +int intf_get_dst(intf_t *i, struct intf_entry *entry, struct addr *dst); +int intf_set(intf_t *i, const struct intf_entry *entry); +int intf_loop(intf_t *i, intf_handler callback, void *arg); +intf_t *intf_close(intf_t *i); +__END_DECLS + +#endif /* DNET_INTF_H */ diff --git a/simulators/gem5/ext/dnet/ip.h b/simulators/gem5/ext/dnet/ip.h new file mode 100644 index 00000000..95b7718f --- /dev/null +++ b/simulators/gem5/ext/dnet/ip.h @@ -0,0 +1,487 @@ +/* + * ip.h + * + * Internet Protocol (RFC 791). + * + * Copyright (c) 2000 Dug Song + * + * $Id: ip.h,v 1.23 2003/03/16 17:39:17 dugsong Exp $ + */ + +#ifndef DNET_IP_H +#define DNET_IP_H + +#define IP_ADDR_LEN 4 /* IP address length */ +#define IP_ADDR_BITS 32 /* IP address bits */ + +#define IP_HDR_LEN 20 /* base IP header length */ +#define IP_OPT_LEN 2 /* base IP option length */ +#define IP_OPT_LEN_MAX 40 +#define IP_HDR_LEN_MAX (IP_HDR_LEN + IP_OPT_LEN_MAX) + +#define IP_LEN_MAX 65535 +#define IP_LEN_MIN IP_HDR_LEN + +typedef uint32_t ip_addr_t; + +#ifndef __GNUC__ +# define __attribute__(x) +# pragma pack(1) +#endif + +/* + * IP header, without options + */ +struct ip_hdr { +#if DNET_BYTESEX == DNET_BIG_ENDIAN + uint8_t ip_v:4, /* version */ + ip_hl:4; /* header length (incl any options) */ +#elif DNET_BYTESEX == DNET_LIL_ENDIAN + uint8_t ip_hl:4, + ip_v:4; +#else +# error "need to include " +#endif + uint8_t ip_tos; /* type of service */ + uint16_t ip_len; /* total length (incl header) */ + uint16_t ip_id; /* identification */ + uint16_t ip_off; /* fragment offset and flags */ + uint8_t ip_ttl; /* time to live */ + uint8_t ip_p; /* protocol */ + uint16_t ip_sum; /* checksum */ + ip_addr_t ip_src; /* source address */ + ip_addr_t ip_dst; /* destination address */ +}; + +/* + * Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474") + */ +#define IP_TOS_DEFAULT 0x00 /* default */ +#define IP_TOS_LOWDELAY 0x10 /* low delay */ +#define IP_TOS_THROUGHPUT 0x08 /* high throughput */ +#define IP_TOS_RELIABILITY 0x04 /* high reliability */ +#define IP_TOS_LOWCOST 0x02 /* low monetary cost - XXX */ +#define IP_TOS_ECT 0x02 /* ECN-capable transport */ +#define IP_TOS_CE 0x01 /* congestion experienced */ + +/* + * IP precedence (high 3 bits of ip_tos), hopefully unused + */ +#define IP_TOS_PREC_ROUTINE 0x00 +#define IP_TOS_PREC_PRIORITY 0x20 +#define IP_TOS_PREC_IMMEDIATE 0x40 +#define IP_TOS_PREC_FLASH 0x60 +#define IP_TOS_PREC_FLASHOVERRIDE 0x80 +#define IP_TOS_PREC_CRITIC_ECP 0xa0 +#define IP_TOS_PREC_INTERNETCONTROL 0xc0 +#define IP_TOS_PREC_NETCONTROL 0xe0 + +/* + * Fragmentation flags (ip_off) + */ +#define IP_RF 0x8000 /* reserved */ +#define IP_DF 0x4000 /* don't fragment */ +#define IP_MF 0x2000 /* more fragments (not last frag) */ +#define IP_OFFMASK 0x1fff /* mask for fragment offset */ + +/* + * Time-to-live (ip_ttl), seconds + */ +#define IP_TTL_DEFAULT 64 /* default ttl, RFC 1122, RFC 1340 */ +#define IP_TTL_MAX 255 /* maximum ttl */ + +/* + * Protocol (ip_p) - http://www.iana.org/assignments/protocol-numbers + */ +#define IP_PROTO_IP 0 /* dummy for IP */ +#define IP_PROTO_HOPOPTS IP_PROTO_IP /* IPv6 hop-by-hop options */ +#define IP_PROTO_ICMP 1 /* ICMP */ +#define IP_PROTO_IGMP 2 /* IGMP */ +#define IP_PROTO_GGP 3 /* gateway-gateway protocol */ +#define IP_PROTO_IPIP 4 /* IP in IP */ +#define IP_PROTO_ST 5 /* ST datagram mode */ +#define IP_PROTO_TCP 6 /* TCP */ +#define IP_PROTO_CBT 7 /* CBT */ +#define IP_PROTO_EGP 8 /* exterior gateway protocol */ +#define IP_PROTO_IGP 9 /* interior gateway protocol */ +#define IP_PROTO_BBNRCC 10 /* BBN RCC monitoring */ +#define IP_PROTO_NVP 11 /* Network Voice Protocol */ +#define IP_PROTO_PUP 12 /* PARC universal packet */ +#define IP_PROTO_ARGUS 13 /* ARGUS */ +#define IP_PROTO_EMCON 14 /* EMCON */ +#define IP_PROTO_XNET 15 /* Cross Net Debugger */ +#define IP_PROTO_CHAOS 16 /* Chaos */ +#define IP_PROTO_UDP 17 /* UDP */ +#define IP_PROTO_MUX 18 /* multiplexing */ +#define IP_PROTO_DCNMEAS 19 /* DCN measurement */ +#define IP_PROTO_HMP 20 /* Host Monitoring Protocol */ +#define IP_PROTO_PRM 21 /* Packet Radio Measurement */ +#define IP_PROTO_IDP 22 /* Xerox NS IDP */ +#define IP_PROTO_TRUNK1 23 /* Trunk-1 */ +#define IP_PROTO_TRUNK2 24 /* Trunk-2 */ +#define IP_PROTO_LEAF1 25 /* Leaf-1 */ +#define IP_PROTO_LEAF2 26 /* Leaf-2 */ +#define IP_PROTO_RDP 27 /* "Reliable Datagram" proto */ +#define IP_PROTO_IRTP 28 /* Inet Reliable Transaction */ +#define IP_PROTO_TP 29 /* ISO TP class 4 */ +#define IP_PROTO_NETBLT 30 /* Bulk Data Transfer */ +#define IP_PROTO_MFPNSP 31 /* MFE Network Services */ +#define IP_PROTO_MERITINP 32 /* Merit Internodal Protocol */ +#define IP_PROTO_SEP 33 /* Sequential Exchange proto */ +#define IP_PROTO_3PC 34 /* Third Party Connect proto */ +#define IP_PROTO_IDPR 35 /* Interdomain Policy Route */ +#define IP_PROTO_XTP 36 /* Xpress Transfer Protocol */ +#define IP_PROTO_DDP 37 /* Datagram Delivery Proto */ +#define IP_PROTO_CMTP 38 /* IDPR Ctrl Message Trans */ +#define IP_PROTO_TPPP 39 /* TP++ Transport Protocol */ +#define IP_PROTO_IL 40 /* IL Transport Protocol */ +#define IP_PROTO_IPV6 41 /* IPv6 */ +#define IP_PROTO_SDRP 42 /* Source Demand Routing */ +#define IP_PROTO_ROUTING 43 /* IPv6 routing header */ +#define IP_PROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IP_PROTO_RSVP 46 /* Reservation protocol */ +#define IP_PROTO_GRE 47 /* General Routing Encap */ +#define IP_PROTO_MHRP 48 /* Mobile Host Routing */ +#define IP_PROTO_ENA 49 /* ENA */ +#define IP_PROTO_ESP 50 /* Encap Security Payload */ +#define IP_PROTO_AH 51 /* Authentication Header */ +#define IP_PROTO_INLSP 52 /* Integated Net Layer Sec */ +#define IP_PROTO_SWIPE 53 /* SWIPE */ +#define IP_PROTO_NARP 54 /* NBMA Address Resolution */ +#define IP_PROTO_MOBILE 55 /* Mobile IP, RFC 2004 */ +#define IP_PROTO_TLSP 56 /* Transport Layer Security */ +#define IP_PROTO_SKIP 57 /* SKIP */ +#define IP_PROTO_ICMPV6 58 /* ICMP for IPv6 */ +#define IP_PROTO_NONE 59 /* IPv6 no next header */ +#define IP_PROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IP_PROTO_ANYHOST 61 /* any host internal proto */ +#define IP_PROTO_CFTP 62 /* CFTP */ +#define IP_PROTO_ANYNET 63 /* any local network */ +#define IP_PROTO_EXPAK 64 /* SATNET and Backroom EXPAK */ +#define IP_PROTO_KRYPTOLAN 65 /* Kryptolan */ +#define IP_PROTO_RVD 66 /* MIT Remote Virtual Disk */ +#define IP_PROTO_IPPC 67 /* Inet Pluribus Packet Core */ +#define IP_PROTO_DISTFS 68 /* any distributed fs */ +#define IP_PROTO_SATMON 69 /* SATNET Monitoring */ +#define IP_PROTO_VISA 70 /* VISA Protocol */ +#define IP_PROTO_IPCV 71 /* Inet Packet Core Utility */ +#define IP_PROTO_CPNX 72 /* Comp Proto Net Executive */ +#define IP_PROTO_CPHB 73 /* Comp Protocol Heart Beat */ +#define IP_PROTO_WSN 74 /* Wang Span Network */ +#define IP_PROTO_PVP 75 /* Packet Video Protocol */ +#define IP_PROTO_BRSATMON 76 /* Backroom SATNET Monitor */ +#define IP_PROTO_SUNND 77 /* SUN ND Protocol */ +#define IP_PROTO_WBMON 78 /* WIDEBAND Monitoring */ +#define IP_PROTO_WBEXPAK 79 /* WIDEBAND EXPAK */ +#define IP_PROTO_EON 80 /* ISO CNLP */ +#define IP_PROTO_VMTP 81 /* Versatile Msg Transport*/ +#define IP_PROTO_SVMTP 82 /* Secure VMTP */ +#define IP_PROTO_VINES 83 /* VINES */ +#define IP_PROTO_TTP 84 /* TTP */ +#define IP_PROTO_NSFIGP 85 /* NSFNET-IGP */ +#define IP_PROTO_DGP 86 /* Dissimilar Gateway Proto */ +#define IP_PROTO_TCF 87 /* TCF */ +#define IP_PROTO_EIGRP 88 /* EIGRP */ +#define IP_PROTO_OSPF 89 /* Open Shortest Path First */ +#define IP_PROTO_SPRITERPC 90 /* Sprite RPC Protocol */ +#define IP_PROTO_LARP 91 /* Locus Address Resolution */ +#define IP_PROTO_MTP 92 /* Multicast Transport Proto */ +#define IP_PROTO_AX25 93 /* AX.25 Frames */ +#define IP_PROTO_IPIPENCAP 94 /* yet-another IP encap */ +#define IP_PROTO_MICP 95 /* Mobile Internet Ctrl */ +#define IP_PROTO_SCCSP 96 /* Semaphore Comm Sec Proto */ +#define IP_PROTO_ETHERIP 97 /* Ethernet in IPv4 */ +#define IP_PROTO_ENCAP 98 /* encapsulation header */ +#define IP_PROTO_ANYENC 99 /* private encryption scheme */ +#define IP_PROTO_GMTP 100 /* GMTP */ +#define IP_PROTO_IFMP 101 /* Ipsilon Flow Mgmt Proto */ +#define IP_PROTO_PNNI 102 /* PNNI over IP */ +#define IP_PROTO_PIM 103 /* Protocol Indep Multicast */ +#define IP_PROTO_ARIS 104 /* ARIS */ +#define IP_PROTO_SCPS 105 /* SCPS */ +#define IP_PROTO_QNX 106 /* QNX */ +#define IP_PROTO_AN 107 /* Active Networks */ +#define IP_PROTO_IPCOMP 108 /* IP Payload Compression */ +#define IP_PROTO_SNP 109 /* Sitara Networks Protocol */ +#define IP_PROTO_COMPAQPEER 110 /* Compaq Peer Protocol */ +#define IP_PROTO_IPXIP 111 /* IPX in IP */ +#define IP_PROTO_VRRP 112 /* Virtual Router Redundancy */ +#define IP_PROTO_PGM 113 /* PGM Reliable Transport */ +#define IP_PROTO_ANY0HOP 114 /* 0-hop protocol */ +#define IP_PROTO_L2TP 115 /* Layer 2 Tunneling Proto */ +#define IP_PROTO_DDX 116 /* D-II Data Exchange (DDX) */ +#define IP_PROTO_IATP 117 /* Interactive Agent Xfer */ +#define IP_PROTO_STP 118 /* Schedule Transfer Proto */ +#define IP_PROTO_SRP 119 /* SpectraLink Radio Proto */ +#define IP_PROTO_UTI 120 /* UTI */ +#define IP_PROTO_SMP 121 /* Simple Message Protocol */ +#define IP_PROTO_SM 122 /* SM */ +#define IP_PROTO_PTP 123 /* Performance Transparency */ +#define IP_PROTO_ISIS 124 /* ISIS over IPv4 */ +#define IP_PROTO_FIRE 125 /* FIRE */ +#define IP_PROTO_CRTP 126 /* Combat Radio Transport */ +#define IP_PROTO_CRUDP 127 /* Combat Radio UDP */ +#define IP_PROTO_SSCOPMCE 128 /* SSCOPMCE */ +#define IP_PROTO_IPLT 129 /* IPLT */ +#define IP_PROTO_SPS 130 /* Secure Packet Shield */ +#define IP_PROTO_PIPE 131 /* Private IP Encap in IP */ +#define IP_PROTO_SCTP 132 /* Stream Ctrl Transmission */ +#define IP_PROTO_FC 133 /* Fibre Channel */ +#define IP_PROTO_RSVPIGN 134 /* RSVP-E2E-IGNORE */ +#define IP_PROTO_RAW 255 /* Raw IP packets */ +#define IP_PROTO_RESERVED IP_PROTO_RAW /* Reserved */ +#define IP_PROTO_MAX 255 + +/* + * Option types (opt_type) - http://www.iana.org/assignments/ip-parameters + */ +#define IP_OPT_CONTROL 0x00 /* control */ +#define IP_OPT_DEBMEAS 0x40 /* debugging & measurement */ +#define IP_OPT_COPY 0x80 /* copy into all fragments */ +#define IP_OPT_RESERVED1 0x20 +#define IP_OPT_RESERVED2 0x60 + +#define IP_OPT_EOL 0 /* end of option list */ +#define IP_OPT_NOP 1 /* no operation */ +#define IP_OPT_SEC (2|IP_OPT_COPY) /* DoD basic security */ +#define IP_OPT_LSRR (3|IP_OPT_COPY) /* loose source route */ +#define IP_OPT_TS (4|IP_OPT_DEBMEAS) /* timestamp */ +#define IP_OPT_ESEC (5|IP_OPT_COPY) /* DoD extended security */ +#define IP_OPT_CIPSO (6|IP_OPT_COPY) /* commercial security */ +#define IP_OPT_RR 7 /* record route */ +#define IP_OPT_SATID (8|IP_OPT_COPY) /* stream ID (obsolete) */ +#define IP_OPT_SSRR (9|IP_OPT_COPY) /* strict source route */ +#define IP_OPT_ZSU 10 /* experimental measurement */ +#define IP_OPT_MTUP 11 /* MTU probe */ +#define IP_OPT_MTUR 12 /* MTU reply */ +#define IP_OPT_FINN (13|IP_OPT_COPY|IP_OPT_DEBMEAS) /* exp flow control */ +#define IP_OPT_VISA (14|IP_OPT_COPY) /* exp access control */ +#define IP_OPT_ENCODE 15 /* ??? */ +#define IP_OPT_IMITD (16|IP_OPT_COPY) /* IMI traffic descriptor */ +#define IP_OPT_EIP (17|IP_OPT_COPY) /* extended IP, RFC 1385 */ +#define IP_OPT_TR (18|IP_OPT_DEBMEAS) /* traceroute */ +#define IP_OPT_ADDEXT (19|IP_OPT_COPY) /* IPv7 ext addr, RFC 1475 */ +#define IP_OPT_RTRALT (20|IP_OPT_COPY) /* router alert, RFC 2113 */ +#define IP_OPT_SDB (21|IP_OPT_COPY) /* directed bcast, RFC 1770 */ +#define IP_OPT_NSAPA (22|IP_OPT_COPY) /* NSAP addresses */ +#define IP_OPT_DPS (23|IP_OPT_COPY) /* dynamic packet state */ +#define IP_OPT_UMP (24|IP_OPT_COPY) /* upstream multicast */ +#define IP_OPT_MAX 25 + +#define IP_OPT_COPIED(o) ((o) & 0x80) +#define IP_OPT_CLASS(o) ((o) & 0x60) +#define IP_OPT_NUMBER(o) ((o) & 0x1f) +#define IP_OPT_TYPEONLY(o) ((o) == IP_OPT_EOL || (o) == IP_OPT_NOP) + +/* + * Security option data - RFC 791, 3.1 + */ +struct ip_opt_data_sec { + uint16_t s; /* security */ + uint16_t c; /* compartments */ + uint16_t h; /* handling restrictions */ + uint8_t tcc[3]; /* transmission control code */ +} __attribute__((__packed__)); + +#define IP_OPT_SEC_UNCLASS 0x0000 /* unclassified */ +#define IP_OPT_SEC_CONFID 0xf135 /* confidential */ +#define IP_OPT_SEC_EFTO 0x789a /* EFTO */ +#define IP_OPT_SEC_MMMM 0xbc4d /* MMMM */ +#define IP_OPT_SEC_PROG 0x5e26 /* PROG */ +#define IP_OPT_SEC_RESTR 0xaf13 /* restricted */ +#define IP_OPT_SEC_SECRET 0xd788 /* secret */ +#define IP_OPT_SEC_TOPSECRET 0x6bc5 /* top secret */ + +/* + * {Loose Source, Record, Strict Source} Route option data - RFC 791, 3.1 + */ +struct ip_opt_data_rr { + uint8_t ptr; /* from start of option, >= 4 */ + uint32_t iplist __flexarr; /* list of IP addresses */ +} __attribute__((__packed__)); + +/* + * Timestamp option data - RFC 791, 3.1 + */ +struct ip_opt_data_ts { + uint8_t ptr; /* from start of option, >= 5 */ +#if DNET_BYTESEX == DNET_BIG_ENDIAN + uint8_t oflw:4, /* number of IPs skipped */ + flg:4; /* address[ / timestamp] flag */ +#elif DNET_BYTESEX == DNET_LIL_ENDIAN + uint8_t flg:4, + oflw:4; +#endif + uint32_t ipts __flexarr; /* IP address [/ timestamp] pairs */ +} __attribute__((__packed__)); + +#define IP_OPT_TS_TSONLY 0 /* timestamps only */ +#define IP_OPT_TS_TSADDR 1 /* IP address / timestamp pairs */ +#define IP_OPT_TS_PRESPEC 3 /* IP address / zero timestamp pairs */ + +/* + * Traceroute option data - RFC 1393, 2.2 + */ +struct ip_opt_data_tr { + uint16_t id; /* ID number */ + uint16_t ohc; /* outbound hop count */ + uint16_t rhc; /* return hop count */ + uint32_t origip; /* originator IP address */ +} __attribute__((__packed__)); + +/* + * IP option (following IP header) + */ +struct ip_opt { + uint8_t opt_type; /* option type */ + uint8_t opt_len; /* option length >= IP_OPT_LEN */ + union ip_opt_data { + struct ip_opt_data_sec sec; /* IP_OPT_SEC */ + struct ip_opt_data_rr rr; /* IP_OPT_{L,S}RR */ + struct ip_opt_data_ts ts; /* IP_OPT_TS */ + uint16_t satid; /* IP_OPT_SATID */ + uint16_t mtu; /* IP_OPT_MTU{P,R} */ + struct ip_opt_data_tr tr; /* IP_OPT_TR */ + uint32_t addext[2]; /* IP_OPT_ADDEXT */ + uint16_t rtralt; /* IP_OPT_RTRALT */ + uint32_t sdb[9]; /* IP_OPT_SDB */ + uint8_t data8[IP_OPT_LEN_MAX - IP_OPT_LEN]; + } opt_data; +} __attribute__((__packed__)); + +#ifndef __GNUC__ +# pragma pack() +#endif + +/* + * Classful addressing + */ +#define IP_CLASSA(i) (((uint32_t)(i) & htonl(0x80000000)) == \ + htonl(0x00000000)) +#define IP_CLASSA_NET (htonl(0xff000000)) +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (htonl(0x00ffffff)) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(i) (((uint32_t)(i) & htonl(0xc0000000)) == \ + htonl(0x80000000)) +#define IP_CLASSB_NET (htonl(0xffff0000)) +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (htonl(0x0000ffff)) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(i) (((uint32_t)(i) & htonl(0xe0000000)) == \ + htonl(0xc0000000)) +#define IP_CLASSC_NET (htonl(0xffffff00)) +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (htonl(0x000000ff)) + +#define IP_CLASSD(i) (((uint32_t)(i) & htonl(0xf0000000)) == \ + htonl(0xe0000000)) +/* These ones aren't really net and host fields, but routing needn't know. */ +#define IP_CLASSD_NET (htonl(0xf0000000)) +#define IP_CLASSD_NSHIFT 28 +#define IP_CLASSD_HOST (htonl(0x0fffffff)) +#define IP_MULTICAST(i) IP_CLASSD(i) + +#define IP_EXPERIMENTAL(i) (((uint32_t)(i) & htonl(0xf0000000)) == \ + htonl(0xf0000000)) +#define IP_BADCLASS(i) (((uint32_t)(i) & htonl(0xf0000000)) == \ + htonl(0xf0000000)) +#define IP_LOCAL_GROUP(i) (((uint32_t)(i) & htonl(0xffffff00)) == \ + htonl(0xe0000000)) +/* + * Reserved addresses + */ +#define IP_ADDR_ANY (htonl(0x00000000)) /* 0.0.0.0 */ +#define IP_ADDR_BROADCAST (htonl(0xffffffff)) /* 255.255.255.255 */ +#define IP_ADDR_LOOPBACK (htonl(0x7f000001)) /* 127.0.0.1 */ +#define IP_ADDR_MCAST_ALL (htonl(0xe0000001)) /* 224.0.0.1 */ +#define IP_ADDR_MCAST_LOCAL (htonl(0xe00000ff)) /* 224.0.0.225 */ + +#define ip_pack_hdr(hdr, tos, len, id, off, ttl, p, src, dst) do { \ + struct ip_hdr *ip_pack_p = (struct ip_hdr *)(hdr); \ + ip_pack_p->ip_v = 4; ip_pack_p->ip_hl = 5; \ + ip_pack_p->ip_tos = tos; ip_pack_p->ip_len = htons(len); \ + ip_pack_p->ip_id = htons(id); ip_pack_p->ip_off = htons(off); \ + ip_pack_p->ip_ttl = ttl; ip_pack_p->ip_p = p; \ + ip_pack_p->ip_src = src; ip_pack_p->ip_dst = dst; \ +} while (0) + +typedef struct ip_handle ip_t; + +__BEGIN_DECLS +ip_t *ip_open(void); +size_t ip_send(ip_t *i, const void *buf, size_t len); +ip_t *ip_close(ip_t *i); + +char *ip_ntop(const ip_addr_t *ip, char *dst, size_t len); +int ip_pton(const char *src, ip_addr_t *dst); +char *ip_ntoa(const ip_addr_t *ip); +#define ip_aton ip_pton + +size_t ip_add_option(void *buf, size_t len, + int proto, const void *optbuf, size_t optlen); +void ip_checksum(void *buf, size_t len); + +inline int +ip_cksum_add(const void *buf, size_t len, int cksum) +{ + uint16_t *sp = (uint16_t *)buf; + int n, sn; + + sn = len / 2; + n = (sn + 15) / 16; + + /* XXX - unroll loop using Duff's device. */ + switch (sn % 16) { + case 0: do { + cksum += *sp++; + case 15: + cksum += *sp++; + case 14: + cksum += *sp++; + case 13: + cksum += *sp++; + case 12: + cksum += *sp++; + case 11: + cksum += *sp++; + case 10: + cksum += *sp++; + case 9: + cksum += *sp++; + case 8: + cksum += *sp++; + case 7: + cksum += *sp++; + case 6: + cksum += *sp++; + case 5: + cksum += *sp++; + case 4: + cksum += *sp++; + case 3: + cksum += *sp++; + case 2: + cksum += *sp++; + case 1: + cksum += *sp++; + } while (--n > 0); + } + if (len & 1) + cksum += htons(*(u_char *)sp << 8); + + return (cksum); +} + +inline uint16_t +ip_cksum_carry(int x) +{ + x = (x >> 16) + (x & 0xffff); + return ~(x + (x >> 16)) & 0xffff; +} + +__END_DECLS + +#endif /* DNET_IP_H */ diff --git a/simulators/gem5/ext/dnet/ip6.h b/simulators/gem5/ext/dnet/ip6.h new file mode 100644 index 00000000..7fae29b4 --- /dev/null +++ b/simulators/gem5/ext/dnet/ip6.h @@ -0,0 +1,183 @@ +/* + * ip6.h + * + * Internet Protocol, Version 6 (RFC 2460). + * + * Copyright (c) 2002 Dug Song + * + * $Id: ip6.h,v 1.6 2004/02/23 10:01:15 dugsong Exp $ + */ + +#ifndef DNET_IP6_H +#define DNET_IP6_H + +#define IP6_ADDR_LEN 16 +#define IP6_ADDR_BITS 128 + +#define IP6_HDR_LEN 40 /* IPv6 header length */ +#define IP6_LEN_MIN IP6_HDR_LEN +#define IP6_LEN_MAX 65535 /* non-jumbo payload */ + +#define IP6_MTU_MIN 1280 /* minimum MTU (1024 + 256) */ + +typedef struct ip6_addr { + uint8_t data[IP6_ADDR_LEN]; +} ip6_addr_t; + +#ifndef __GNUC__ +# define __attribute__(x) +# pragma pack(1) +#endif + +/* + * IPv6 header + */ +struct ip6_hdr { + union { + struct ip6_hdr_ctl { + uint32_t ip6_un1_flow; /* 20 bits of flow ID */ + uint16_t ip6_un1_plen; /* payload length */ + uint8_t ip6_un1_nxt; /* next header */ + uint8_t ip6_un1_hlim; /* hop limit */ + } ip6_un1; + uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */ + } ip6_ctlun; + ip6_addr_t ip6_src; + ip6_addr_t ip6_dst; +} __attribute__((__packed__)); + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt /* IP_PROTO_* */ +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define IP6_VERSION 0x60 +#define IP6_VERSION_MASK 0xf0 /* ip6_vfc version */ + +#if DNET_BYTESEX == DNET_BIG_ENDIAN +#define IP6_FLOWINFO_MASK 0x0fffffff /* ip6_flow info (28 bits) */ +#define IP6_FLOWLABEL_MASK 0x000fffff /* ip6_flow label (20 bits) */ +#elif DNET_BYTESEX == DNET_LIL_ENDIAN +#define IP6_FLOWINFO_MASK 0xffffff0f /* ip6_flow info (28 bits) */ +#define IP6_FLOWLABEL_MASK 0xffff0f00 /* ip6_flow label (20 bits) */ +#endif + +/* + * Hop limit (ip6_hlim) + */ +#define IP6_HLIM_DEFAULT 64 +#define IP6_HLIM_MAX 255 + +/* + * Preferred extension header order from RFC 2460, 4.1: + * + * IP_PROTO_IPV6, IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS, IP_PROTO_ROUTING, + * IP_PROTO_FRAGMENT, IP_PROTO_AH, IP_PROTO_ESP, IP_PROTO_DSTOPTS, IP_PROTO_* + */ + +/* + * Routing header data (IP_PROTO_ROUTING) + */ +struct ip6_ext_data_routing { + uint8_t type; /* routing type */ + uint8_t segleft; /* segments left */ + /* followed by routing type specific data */ +} __attribute__((__packed__)); + +struct ip6_ext_data_routing0 { + uint8_t type; /* always zero */ + uint8_t segleft; /* segments left */ + uint8_t reserved; /* reserved field */ + uint8_t slmap[3]; /* strict/loose bit map */ + ip6_addr_t addr[1]; /* up to 23 addresses */ +} __attribute__((__packed__)); + +/* + * Fragment header data (IP_PROTO_FRAGMENT) + */ +struct ip6_ext_data_fragment { + uint16_t offlg; /* offset, reserved, and flag */ + uint32_t ident; /* identification */ +} __attribute__((__packed__)); + +/* + * Fragmentation offset, reserved, and flags (offlg) + */ +#if DNET_BYTESEX == DNET_BIG_ENDIAN +#define IP6_OFF_MASK 0xfff8 /* mask out offset from offlg */ +#define IP6_RESERVED_MASK 0x0006 /* reserved bits in offlg */ +#define IP6_MORE_FRAG 0x0001 /* more-fragments flag */ +#elif DNET_BYTESEX == DNET_LIL_ENDIAN +#define IP6_OFF_MASK 0xf8ff /* mask out offset from offlg */ +#define IP6_RESERVED_MASK 0x0600 /* reserved bits in offlg */ +#define IP6_MORE_FRAG 0x0100 /* more-fragments flag */ +#endif + +/* + * Option types, for IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS headers + */ +#define IP6_OPT_PAD1 0x00 /* 00 0 00000 */ +#define IP6_OPT_PADN 0x01 /* 00 0 00001 */ +#define IP6_OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ +#define IP6_OPT_JUMBO_LEN 6 +#define IP6_OPT_RTALERT 0x05 /* 00 0 00101 */ +#define IP6_OPT_RTALERT_LEN 4 +#define IP6_OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ +#define IP6_OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ +#define IP6_OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ +#define IP6_OPT_LEN_MIN 2 + +#define IP6_OPT_TYPE(o) ((o) & 0xC0) /* high 2 bits of opt_type */ +#define IP6_OPT_TYPE_SKIP 0x00 /* continue processing on failure */ +#define IP6_OPT_TYPE_DISCARD 0x40 /* discard packet on failure */ +#define IP6_OPT_TYPE_FORCEICMP 0x80 /* discard and send ICMP on failure */ +#define IP6_OPT_TYPE_ICMP 0xC0 /* ...only if non-multicast dst */ + +#define IP6_OPT_MUTABLE 0x20 /* option data may change en route */ + +/* + * Extension header (chained via {ip6,ext}_nxt, following IPv6 header) + */ +struct ip6_ext_hdr { + uint8_t ext_nxt; /* next header */ + uint8_t ext_len; /* following length in units of 8 octets */ + union { + struct ip6_ext_data_routing routing; + struct ip6_ext_data_fragment fragment; + } ext_data; +} __attribute__((__packed__)); + +#ifndef __GNUC__ +# pragma pack() +#endif + +/* + * Reserved addresses + */ +#define IP6_ADDR_UNSPEC \ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +#define IP6_ADDR_LOOPBACK \ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + +#define ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, src, dst) do { \ + struct ip6_hdr *ip6 = (struct ip6_hdr *)(hdr); \ + ip6->ip6_flow = htonl(((uint32_t)(fc) << 28) & \ + (IP6_FLOWLABEL_MASK | (fl))); \ + ip6->ip6_vfc = (IP6_VERSION | ((fc) >> 4)); \ + ip6->ip6_plen = htons((plen)); \ + ip6->ip6_nxt = (nxt); ip6->ip6_hlim = (hlim); \ + memmove(&ip6->ip6_src, &(src), IP6_ADDR_LEN); \ + memmove(&ip6->ip6_dst, &(dst), IP6_ADDR_LEN); \ +} while (0); + +__BEGIN_DECLS +char *ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t size); +int ip6_pton(const char *src, ip6_addr_t *dst); +char *ip6_ntoa(const ip6_addr_t *ip6); +#define ip6_aton ip6_pton + +void ip6_checksum(void *buf, size_t len); +__END_DECLS + +#endif /* DNET_IP6_H */ diff --git a/simulators/gem5/ext/dnet/os.h b/simulators/gem5/ext/dnet/os.h new file mode 100644 index 00000000..cae24478 --- /dev/null +++ b/simulators/gem5/ext/dnet/os.h @@ -0,0 +1,117 @@ +/* + * os.h + * + * Sleazy OS-specific defines. + * + * Copyright (c) 2000 Dug Song + * + * $Id: os.h,v 1.10 2004/05/04 03:19:42 dugsong Exp $ + */ + +#ifndef DNET_OS_H +#define DNET_OS_H + +#ifdef _WIN32 +# include +# include +# include +/* XXX */ +# undef IP_OPT_LSRR +# undef IP_OPT_TS +# undef IP_OPT_RR +# undef IP_OPT_SSRR +#else +# include +# include +# include +# include +# include +# include +# ifdef __bsdi__ +# include + typedef u_int8_t uint8_t; + typedef u_int16_t uint16_t; + typedef u_int32_t uint32_t; + typedef u_int64_t uint64_t; +# else +# include +# endif +#endif + +#define DNET_LIL_ENDIAN 1234 +#define DNET_BIG_ENDIAN 4321 + +/* BSD and IRIX */ +#ifdef BYTE_ORDER +#if BYTE_ORDER == LITTLE_ENDIAN +# define DNET_BYTESEX DNET_LIL_ENDIAN +#elif BYTE_ORDER == BIG_ENDIAN +# define DNET_BYTESEX DNET_BIG_ENDIAN +#endif +#endif + +/* Linux */ +#ifdef __BYTE_ORDER +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define DNET_BYTESEX DNET_LIL_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN +# define DNET_BYTESEX DNET_BIG_ENDIAN +#endif +#endif + +/* Solaris */ +#if defined(_BIT_FIELDS_LTOH) +# define DNET_BYTESEX DNET_LIL_ENDIAN +#elif defined (_BIT_FIELDS_HTOL) +# define DNET_BYTESEX DNET_BIG_ENDIAN +#endif + +/* Nastiness from old BIND code. */ +#ifndef DNET_BYTESEX +# if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) +# define DNET_BYTESEX DNET_LIL_ENDIAN +# elif defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || defined(__ia64) || \ + defined (BIT_ZERO_ON_LEFT) || defined(m68k) +# define DNET_BYTESEX DNET_BIG_ENDIAN +# else +# error "bytesex unknown" +# endif +#endif + +/* C++ support. */ +#undef __BEGIN_DECLS +#undef __END_DECLS +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } /* extern "C" */ +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + +/* Support for flexible arrays. */ +#undef __flexarr +#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)) +/* GCC 2.97 supports C99 flexible array members. */ +# define __flexarr [] +#else +# ifdef __GNUC__ +# define __flexarr [0] +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __flexarr [] +# else +/* Some other non-C99 compiler. Approximate with [1]. */ +# define __flexarr [1] +# endif +# endif +#endif + +#endif /* DNET_OS_H */ diff --git a/simulators/gem5/ext/dnet/rand.h b/simulators/gem5/ext/dnet/rand.h new file mode 100644 index 00000000..49121930 --- /dev/null +++ b/simulators/gem5/ext/dnet/rand.h @@ -0,0 +1,33 @@ +/* + * rand.h + * + * Pseudo-random number generation, based on OpenBSD arc4random(). + * + * Copyright (c) 2000 Dug Song + * Copyright (c) 1996 David Mazieres + * + * $Id: rand.h,v 1.4 2002/04/07 19:01:25 dugsong Exp $ + */ + +#ifndef DNET_RAND_H +#define DNET_RAND_H + +typedef struct rand_handle rand_t; + +__BEGIN_DECLS +rand_t *rand_open(void); + +int rand_get(rand_t *r, void *buf, size_t len); +int rand_set(rand_t *r, const void *seed, size_t len); +int rand_add(rand_t *r, const void *buf, size_t len); + +uint8_t rand_uint8(rand_t *r); +uint16_t rand_uint16(rand_t *r); +uint32_t rand_uint32(rand_t *r); + +int rand_shuffle(rand_t *r, void *base, size_t nmemb, size_t size); + +rand_t *rand_close(rand_t *r); +__END_DECLS + +#endif /* DNET_RAND_H */ diff --git a/simulators/gem5/ext/dnet/route.h b/simulators/gem5/ext/dnet/route.h new file mode 100644 index 00000000..74c21419 --- /dev/null +++ b/simulators/gem5/ext/dnet/route.h @@ -0,0 +1,35 @@ +/* + * route.c + * + * Kernel route table operations. + * + * Copyright (c) 2000 Dug Song + * + * $Id: route.h,v 1.6 2002/02/04 04:02:22 dugsong Exp $ + */ + +#ifndef DNET_ROUTE_H +#define DNET_ROUTE_H + +/* + * Routing table entry + */ +struct route_entry { + struct addr route_dst; /* destination address */ + struct addr route_gw; /* gateway address */ +}; + +typedef struct route_handle route_t; + +typedef int (*route_handler)(const struct route_entry *entry, void *arg); + +__BEGIN_DECLS +route_t *route_open(void); +int route_add(route_t *r, const struct route_entry *entry); +int route_delete(route_t *r, const struct route_entry *entry); +int route_get(route_t *r, struct route_entry *entry); +int route_loop(route_t *r, route_handler callback, void *arg); +route_t *route_close(route_t *r); +__END_DECLS + +#endif /* DNET_ROUTE_H */ diff --git a/simulators/gem5/ext/dnet/tcp.h b/simulators/gem5/ext/dnet/tcp.h new file mode 100644 index 00000000..00894638 --- /dev/null +++ b/simulators/gem5/ext/dnet/tcp.h @@ -0,0 +1,158 @@ +/* + * tcp.h + * + * Transmission Control Protocol (RFC 793). + * + * Copyright (c) 2000 Dug Song + * + * $Id: tcp.h,v 1.17 2004/02/23 10:02:11 dugsong Exp $ + */ + +#ifndef DNET_TCP_H +#define DNET_TCP_H + +#define TCP_HDR_LEN 20 /* base TCP header length */ +#define TCP_OPT_LEN 2 /* base TCP option length */ +#define TCP_OPT_LEN_MAX 40 +#define TCP_HDR_LEN_MAX (TCP_HDR_LEN + TCP_OPT_LEN_MAX) + +#ifndef __GNUC__ +# define __attribute__(x) +# pragma pack(1) +#endif + +/* + * TCP header, without options + */ +struct tcp_hdr { + uint16_t th_sport; /* source port */ + uint16_t th_dport; /* destination port */ + uint32_t th_seq; /* sequence number */ + uint32_t th_ack; /* acknowledgment number */ +#if DNET_BYTESEX == DNET_BIG_ENDIAN + uint8_t th_off:4, /* data offset */ + th_x2:4; /* (unused) */ +#elif DNET_BYTESEX == DNET_LIL_ENDIAN + uint8_t th_x2:4, + th_off:4; +#else +# error "need to include " +#endif + uint8_t th_flags; /* control flags */ + uint16_t th_win; /* window */ + uint16_t th_sum; /* checksum */ + uint16_t th_urp; /* urgent pointer */ +}; + +/* + * TCP control flags (th_flags) + */ +#define TH_FIN 0x01 /* end of data */ +#define TH_SYN 0x02 /* synchronize sequence numbers */ +#define TH_RST 0x04 /* reset connection */ +#define TH_PUSH 0x08 /* push */ +#define TH_ACK 0x10 /* acknowledgment number set */ +#define TH_URG 0x20 /* urgent pointer set */ +#define TH_ECE 0x40 /* ECN echo, RFC 3168 */ +#define TH_CWR 0x80 /* congestion window reduced */ + +#define TCP_PORT_MAX 65535 /* maximum port */ +#define TCP_WIN_MAX 65535 /* maximum (unscaled) window */ + +/* + * Sequence number comparison macros + */ +#define TCP_SEQ_LT(a,b) ((int)((a)-(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((int)((a)-(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) + +/* + * TCP FSM states + */ +#define TCP_STATE_CLOSED 0 /* closed */ +#define TCP_STATE_LISTEN 1 /* listening from connection */ +#define TCP_STATE_SYN_SENT 2 /* active, have sent SYN */ +#define TCP_STATE_SYN_RECEIVED 3 /* have sent and received SYN */ + +#define TCP_STATE_ESTABLISHED 4 /* established */ +#define TCP_STATE_CLOSE_WAIT 5 /* rcvd FIN, waiting for close */ + +#define TCP_STATE_FIN_WAIT_1 6 /* have closed, sent FIN */ +#define TCP_STATE_CLOSING 7 /* closed xchd FIN, await FIN-ACK */ +#define TCP_STATE_LAST_ACK 8 /* had FIN and close, await FIN-ACK */ + +#define TCP_STATE_FIN_WAIT_2 9 /* have closed, FIN is acked */ +#define TCP_STATE_TIME_WAIT 10 /* in 2*MSL quiet wait after close */ +#define TCP_STATE_MAX 11 + +/* + * Options (opt_type) - http://www.iana.org/assignments/tcp-parameters + */ +#define TCP_OPT_EOL 0 /* end of option list */ +#define TCP_OPT_NOP 1 /* no operation */ +#define TCP_OPT_MSS 2 /* maximum segment size */ +#define TCP_OPT_WSCALE 3 /* window scale factor, RFC 1072 */ +#define TCP_OPT_SACKOK 4 /* SACK permitted, RFC 2018 */ +#define TCP_OPT_SACK 5 /* SACK, RFC 2018 */ +#define TCP_OPT_ECHO 6 /* echo (obsolete), RFC 1072 */ +#define TCP_OPT_ECHOREPLY 7 /* echo reply (obsolete), RFC 1072 */ +#define TCP_OPT_TIMESTAMP 8 /* timestamp, RFC 1323 */ +#define TCP_OPT_POCONN 9 /* partial order conn, RFC 1693 */ +#define TCP_OPT_POSVC 10 /* partial order service, RFC 1693 */ +#define TCP_OPT_CC 11 /* connection count, RFC 1644 */ +#define TCP_OPT_CCNEW 12 /* CC.NEW, RFC 1644 */ +#define TCP_OPT_CCECHO 13 /* CC.ECHO, RFC 1644 */ +#define TCP_OPT_ALTSUM 14 /* alt checksum request, RFC 1146 */ +#define TCP_OPT_ALTSUMDATA 15 /* alt checksum data, RFC 1146 */ +#define TCP_OPT_SKEETER 16 /* Skeeter */ +#define TCP_OPT_BUBBA 17 /* Bubba */ +#define TCP_OPT_TRAILSUM 18 /* trailer checksum */ +#define TCP_OPT_MD5 19 /* MD5 signature, RFC 2385 */ +#define TCP_OPT_SCPS 20 /* SCPS capabilities */ +#define TCP_OPT_SNACK 21 /* selective negative acks */ +#define TCP_OPT_REC 22 /* record boundaries */ +#define TCP_OPT_CORRUPT 23 /* corruption experienced */ +#define TCP_OPT_SNAP 24 /* SNAP */ +#define TCP_OPT_TCPCOMP 26 /* TCP compression filter */ +#define TCP_OPT_MAX 27 + +#define TCP_OPT_TYPEONLY(type) \ + ((type) == TCP_OPT_EOL || (type) == TCP_OPT_NOP) + +/* + * TCP option (following TCP header) + */ +struct tcp_opt { + uint8_t opt_type; /* option type */ + uint8_t opt_len; /* option length >= TCP_OPT_LEN */ + union tcp_opt_data { + uint16_t mss; /* TCP_OPT_MSS */ + uint8_t wscale; /* TCP_OPT_WSCALE */ + uint16_t sack[19]; /* TCP_OPT_SACK */ + uint32_t echo; /* TCP_OPT_ECHO{REPLY} */ + uint32_t timestamp[2]; /* TCP_OPT_TIMESTAMP */ + uint32_t cc; /* TCP_OPT_CC{NEW,ECHO} */ + uint8_t cksum; /* TCP_OPT_ALTSUM */ + uint8_t md5[16]; /* TCP_OPT_MD5 */ + uint8_t data8[TCP_OPT_LEN_MAX - TCP_OPT_LEN]; + } opt_data; +} __attribute__((__packed__)); + +#ifndef __GNUC__ +# pragma pack() +#endif + +#define tcp_pack_hdr(hdr, sport, dport, seq, ack, flags, win, urp) do { \ + struct tcp_hdr *tcp_pack_p = (struct tcp_hdr *)(hdr); \ + tcp_pack_p->th_sport = htons(sport); \ + tcp_pack_p->th_dport = htons(dport); \ + tcp_pack_p->th_seq = htonl(seq); \ + tcp_pack_p->th_ack = htonl(ack); \ + tcp_pack_p->th_x2 = 0; tcp_pack_p->th_off = 5; \ + tcp_pack_p->th_flags = flags; \ + tcp_pack_p->th_win = htons(win); \ + tcp_pack_p->th_urp = htons(urp); \ +} while (0) + +#endif /* DNET_TCP_H */ diff --git a/simulators/gem5/ext/dnet/udp.h b/simulators/gem5/ext/dnet/udp.h new file mode 100644 index 00000000..73839a92 --- /dev/null +++ b/simulators/gem5/ext/dnet/udp.h @@ -0,0 +1,32 @@ +/* + * udp.h + * + * User Datagram Protocol (RFC 768). + * + * Copyright (c) 2000 Dug Song + * + * $Id: udp.h,v 1.8 2002/04/02 05:05:39 dugsong Exp $ + */ + +#ifndef DNET_UDP_H +#define DNET_UDP_H + +#define UDP_HDR_LEN 8 + +struct udp_hdr { + uint16_t uh_sport; /* source port */ + uint16_t uh_dport; /* destination port */ + uint16_t uh_ulen; /* udp length (including header) */ + uint16_t uh_sum; /* udp checksum */ +}; + +#define UDP_PORT_MAX 65535 + +#define udp_pack_hdr(hdr, sport, dport, ulen) do { \ + struct udp_hdr *udp_pack_p = (struct udp_hdr *)(hdr); \ + udp_pack_p->uh_sport = htons(sport); \ + udp_pack_p->uh_dport = htons(dport); \ + udp_pack_p->uh_ulen = htons(ulen); \ +} while (0) + +#endif /* DNET_UDP_H */ diff --git a/simulators/gem5/ext/gzstream/LICENSE b/simulators/gem5/ext/gzstream/LICENSE new file mode 100644 index 00000000..f3f1b3b6 --- /dev/null +++ b/simulators/gem5/ext/gzstream/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/simulators/gem5/ext/gzstream/SConscript b/simulators/gem5/ext/gzstream/SConscript new file mode 100644 index 00000000..b93f5e36 --- /dev/null +++ b/simulators/gem5/ext/gzstream/SConscript @@ -0,0 +1,38 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('main') + +main.Library('gzstream', [main.SharedObject('gzstream.cc')]) + +main.Prepend(CPPPATH=Dir('.')) +main.Append(LIBS=['gzstream']) +main.Prepend(LIBPATH=[Dir('.')]) + diff --git a/simulators/gem5/ext/gzstream/VERSION b/simulators/gem5/ext/gzstream/VERSION new file mode 100644 index 00000000..511137de --- /dev/null +++ b/simulators/gem5/ext/gzstream/VERSION @@ -0,0 +1 @@ +1.5 (08 Jan 2003) diff --git a/simulators/gem5/ext/gzstream/gzstream.cc b/simulators/gem5/ext/gzstream/gzstream.cc new file mode 100644 index 00000000..c804a33c --- /dev/null +++ b/simulators/gem5/ext/gzstream/gzstream.cc @@ -0,0 +1,165 @@ +// ============================================================================ +// gzstream, C++ iostream classes wrapping the zlib compression library. +// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ============================================================================ +// +// File : gzstream.C +// Revision : $Revision: 1.7 $ +// Revision_date : $Date: 2003/01/08 14:41:27 $ +// Author(s) : Deepak Bandyopadhyay, Lutz Kettner +// +// Standard streambuf implementation following Nicolai Josuttis, "The +// Standard C++ Library". +// ============================================================================ + +#include +#include +#include // for memcpy + +#ifdef GZSTREAM_NAMESPACE +namespace GZSTREAM_NAMESPACE { +#endif + +// ---------------------------------------------------------------------------- +// Internal classes to implement gzstream. See header file for user classes. +// ---------------------------------------------------------------------------- + +// -------------------------------------- +// class gzstreambuf: +// -------------------------------------- + +gzstreambuf* gzstreambuf::open( const char* name, int open_mode) { + if ( is_open()) + return (gzstreambuf*)0; + mode = open_mode; + // no append nor read/write mode + if ((mode & std::ios::ate) || (mode & std::ios::app) + || ((mode & std::ios::in) && (mode & std::ios::out))) + return (gzstreambuf*)0; + char fmode[10]; + char* fmodeptr = fmode; + if ( mode & std::ios::in) + *fmodeptr++ = 'r'; + else if ( mode & std::ios::out) + *fmodeptr++ = 'w'; + *fmodeptr++ = 'b'; + *fmodeptr = '\0'; + file = gzopen( name, fmode); + if (file == 0) + return (gzstreambuf*)0; + opened = 1; + return this; +} + +gzstreambuf * gzstreambuf::close() { + if ( is_open()) { + sync(); + opened = 0; + if ( gzclose( file) == Z_OK) + return this; + } + return (gzstreambuf*)0; +} + +int gzstreambuf::underflow() { // used for input buffer only + if ( gptr() && ( gptr() < egptr())) + return * reinterpret_cast( gptr()); + + if ( ! (mode & std::ios::in) || ! opened) + return EOF; + // Josuttis' implementation of inbuf + int n_putback = gptr() - eback(); + if ( n_putback > 4) + n_putback = 4; + memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback); + + int num = gzread( file, buffer+4, bufferSize-4); + if (num <= 0) // ERROR or EOF + return EOF; + + // reset buffer pointers + setg( buffer + (4 - n_putback), // beginning of putback area + buffer + 4, // read position + buffer + 4 + num); // end of buffer + + // return next character + return *reinterpret_cast(gptr()); +} + +int gzstreambuf::flush_buffer() { + // Separate the writing of the buffer from overflow() and + // sync() operation. + int w = pptr() - pbase(); + if ( gzwrite( file, pbase(), w) != w) + return EOF; + pbump( -w); + return w; +} + +int gzstreambuf::overflow( int c) { // used for output buffer only + if ( ! ( mode & std::ios::out) || ! opened) + return EOF; + if (c != EOF) { + *pptr() = c; + pbump(1); + } + if ( flush_buffer() == EOF) + return EOF; + return c; +} + +int gzstreambuf::sync() { + // Changed to use flush_buffer() instead of overflow( EOF) + // which caused improper behavior with std::endl and flush(), + // bug reported by Vincent Ricard. + if ( pptr() && pptr() > pbase()) { + if ( flush_buffer() == EOF) + return -1; + } + return 0; +} + +// -------------------------------------- +// class gzstreambase: +// -------------------------------------- + +gzstreambase::gzstreambase( const char* name, int mode) { + init( &buf); + open( name, mode); +} + +gzstreambase::~gzstreambase() { + buf.close(); +} + +void gzstreambase::open( const char* name, int open_mode) { + if ( ! buf.open( name, open_mode)) + clear( rdstate() | std::ios::badbit); +} + +void gzstreambase::close() { + if ( buf.is_open()) + if ( ! buf.close()) + clear( rdstate() | std::ios::badbit); +} + +#ifdef GZSTREAM_NAMESPACE +} // namespace GZSTREAM_NAMESPACE +#endif + +// ============================================================================ +// EOF // diff --git a/simulators/gem5/ext/gzstream/gzstream.hh b/simulators/gem5/ext/gzstream/gzstream.hh new file mode 100644 index 00000000..b43fd23b --- /dev/null +++ b/simulators/gem5/ext/gzstream/gzstream.hh @@ -0,0 +1,122 @@ +// ============================================================================ +// gzstream, C++ iostream classes wrapping the zlib compression library. +// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ============================================================================ +// +// File : gzstream.h +// Revision : $Revision: 1.5 $ +// Revision_date : $Date: 2002/04/26 23:30:15 $ +// Author(s) : Deepak Bandyopadhyay, Lutz Kettner +// +// Standard streambuf implementation following Nicolai Josuttis, "The +// Standard C++ Library". +// ============================================================================ + +#ifndef GZSTREAM_H +#define GZSTREAM_H 1 + +// standard C++ with new header file names and std:: namespace +#include +#include +#include + +#ifdef GZSTREAM_NAMESPACE +namespace GZSTREAM_NAMESPACE { +#endif + +// ---------------------------------------------------------------------------- +// Internal classes to implement gzstream. See below for user classes. +// ---------------------------------------------------------------------------- + +class gzstreambuf : public std::streambuf { +private: + static const int bufferSize = 47+256; // size of data buff + // totals 512 bytes under g++ for igzstream at the end. + + gzFile file; // file handle for compressed file + char buffer[bufferSize]; // data buffer + char opened; // open/close state of stream + int mode; // I/O mode + + int flush_buffer(); +public: + gzstreambuf() : opened(0) { + setp( buffer, buffer + (bufferSize-1)); + setg( buffer + 4, // beginning of putback area + buffer + 4, // read position + buffer + 4); // end position + // ASSERT: both input & output capabilities will not be used together + } + int is_open() { return opened; } + gzstreambuf* open( const char* name, int open_mode); + gzstreambuf* close(); + ~gzstreambuf() { close(); } + + virtual int overflow( int c = EOF); + virtual int underflow(); + virtual int sync(); +}; + +class gzstreambase : virtual public std::ios { +protected: + gzstreambuf buf; +public: + gzstreambase() { init(&buf); } + gzstreambase( const char* name, int open_mode); + ~gzstreambase(); + int is_open() { return buf.is_open(); } + void open( const char* name, int open_mode); + void close(); + gzstreambuf* rdbuf() { return &buf; } +}; + +// ---------------------------------------------------------------------------- +// User classes. Use igzstream and ogzstream analogously to ifstream and +// ofstream respectively. They read and write files based on the gz* +// function interface of the zlib. Files are compatible with gzip compression. +// ---------------------------------------------------------------------------- + +class igzstream : public gzstreambase, public std::istream { +public: + igzstream() : std::istream( &buf) {} + igzstream( const char* name, int open_mode = std::ios::in) + : gzstreambase( name, open_mode | std::ios::in), std::istream( &buf) {} + gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } + void open( const char* name, int open_mode = std::ios::in) { + gzstreambase::open( name, open_mode); + } +}; + +class ogzstream : public gzstreambase, public std::ostream { +public: + ogzstream() : std::ostream( &buf) {} + ogzstream( const char* name, int mode = std::ios::out) + : gzstreambase( name, mode | std::ios::out), std::ostream( &buf) {} + gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } + void open( const char* name, int open_mode = std::ios::out) { + gzstreambase::open( name, open_mode); + } +}; + +#ifdef GZSTREAM_NAMESPACE +} // namespace GZSTREAM_NAMESPACE +#endif + +#endif // GZSTREAM_H +// ============================================================================ +// EOF // + diff --git a/simulators/gem5/ext/libelf/SConscript b/simulators/gem5/ext/libelf/SConscript new file mode 100644 index 00000000..56983d12 --- /dev/null +++ b/simulators/gem5/ext/libelf/SConscript @@ -0,0 +1,133 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import os, subprocess + +Import('main') + +from m5.util import compareVersions + +elf_files = [] +def ElfFile(filename): + elf_files.append(File(filename)) + +ElfFile('elf_begin.c') +ElfFile('elf_cntl.c') +ElfFile('elf_data.c') +ElfFile('elf_end.c') +ElfFile('elf_errmsg.c') +ElfFile('elf_errno.c') +ElfFile('elf_fill.c') +ElfFile('elf_flag.c') +ElfFile('elf_getarhdr.c') +ElfFile('elf_getarsym.c') +ElfFile('elf_getbase.c') +ElfFile('elf_getident.c') +ElfFile('elf_hash.c') +ElfFile('elf_kind.c') +ElfFile('elf_memory.c') +ElfFile('elf_next.c') +ElfFile('elf_phnum.c') +ElfFile('elf_rand.c') +ElfFile('elf_rawfile.c') +ElfFile('elf_scn.c') +ElfFile('elf_shnum.c') +ElfFile('elf_shstrndx.c') +ElfFile('elf_strptr.c') +ElfFile('elf_update.c') +ElfFile('elf_version.c') +ElfFile('gelf_checksum.c') +ElfFile('gelf_dyn.c') +ElfFile('gelf_ehdr.c') +ElfFile('gelf_fsize.c') +ElfFile('gelf_getclass.c') +ElfFile('gelf_phdr.c') +ElfFile('gelf_rel.c') +ElfFile('gelf_rela.c') +ElfFile('gelf_shdr.c') +ElfFile('gelf_sym.c') +ElfFile('gelf_symshndx.c') +ElfFile('gelf_xlate.c') +ElfFile('libelf.c') +ElfFile('libelf_align.c') +ElfFile('libelf_allocate.c') +ElfFile('libelf_ar.c') +ElfFile('libelf_checksum.c') +ElfFile('libelf_data.c') +ElfFile('libelf_ehdr.c') +ElfFile('libelf_extended.c') +ElfFile('libelf_phdr.c') +ElfFile('libelf_shdr.c') +ElfFile('libelf_xlate.c') + +ElfFile('libelf_convert.c') +ElfFile('libelf_fsize.c') +ElfFile('libelf_msize.c') + +m4env = main.Clone() +if m4env['GCC']: + if compareVersions(m4env['GCC_VERSION'], '4') >= 0: + m4env.Append(CCFLAGS=['-Wno-pointer-sign']) + if compareVersions(m4env['GCC_VERSION'], '4.6') >= 0: + m4env.Append(CCFLAGS=['-Wno-unused-but-set-variable', + '-Wno-implicit-function-declaration']) +if m4env['CLANG']: + m4env.Append(CCFLAGS=['-Wno-initializer-overrides', '-Wno-pointer-sign']) +m4env.Append(CCFLAGS=['-Wno-implicit']) +del m4env['CPPPATH'] + +# If we have gm4 use it +if m4env.Detect('gm4'): + m4env['M4'] = 'gm4' + +# Check that m4 is available +import SCons.Tool.m4 +if not SCons.Tool.m4.exists(m4env): + print "Error: Can't find version of M4 macro processor. " + \ + "Please install M4 and try again." + Exit(1) + +m4env.Append(M4FLAGS=['-DSRCDIR=%s' % Dir('.').path]) +m4env['M4COM'] = '$M4 $M4FLAGS $SOURCES > $TARGET' +m4env.M4(target=File('libelf_convert.c'), + source=[File('elf_types.m4'), File('libelf_convert.m4')]) +m4env.M4(target=File('libelf_fsize.c'), + source=[File('elf_types.m4'), File('libelf_fsize.m4')]) +m4env.M4(target=File('libelf_msize.c'), + source=[File('elf_types.m4'), File('libelf_msize.m4')]) + +# Build libelf as a static library with PIC code so it can be linked +# into either m5 or the library +m4env.Library('elf', [m4env.SharedObject(f) for f in elf_files]) + +main.Prepend(CPPPATH=Dir('.')) +main.Append(LIBS=['elf']) +main.Prepend(LIBPATH=[Dir('.')]) + diff --git a/simulators/gem5/ext/libelf/_libelf.h b/simulators/gem5/ext/libelf/_libelf.h new file mode 100644 index 00000000..f6cec6e3 --- /dev/null +++ b/simulators/gem5/ext/libelf/_libelf.h @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/_libelf.h,v 1.2 2006/12/25 02:22:22 jkoshy Exp $ + */ + +#ifndef __LIBELF_H_ +#define __LIBELF_H_ + +#include "elf_queue.h" +#include "libelf.h" + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +/* + * Library-private data structures. + */ + +#define LIBELF_MSG_SIZE 256 + +struct _libelf_globals { + int libelf_arch; + unsigned int libelf_byteorder; + int libelf_class; + int libelf_error; + int libelf_fillchar; + unsigned int libelf_version; + char libelf_msg[LIBELF_MSG_SIZE]; +}; + +struct _libelf_globals *_libelf_private(); + +#define LIBELF_PRIVATE(N) (_libelf_private()->libelf_##N) + +#define LIBELF_ELF_ERROR_MASK 0xFF +#define LIBELF_OS_ERROR_SHIFT 8 + +#define LIBELF_SET_ERROR(E, O) do { \ + LIBELF_PRIVATE(error) = ((ELF_E_##E & LIBELF_ELF_ERROR_MASK)| \ + ((O) << LIBELF_OS_ERROR_SHIFT)); \ + } while (0) + +#define LIBELF_ADJUST_AR_SIZE(S) (((S) + 1U) & ~1U) + +/* + * Flags for library internal use. These use the upper 16 bits of a + * flags field. + */ +#define LIBELF_F_MALLOCED 0x010000 /* whether data was malloc'ed */ +#define LIBELF_F_MMAP 0x020000 /* whether e_rawfile was mmap'ed */ +#define LIBELF_F_SHDRS_LOADED 0x040000 /* whether all shdrs were read in */ + +struct _Elf { + int e_activations; /* activation count */ + Elf_Arhdr *e_arhdr; /* header for archive members */ + unsigned int e_byteorder; /* ELFDATA* */ + int e_class; /* ELFCLASS* */ + Elf_Cmd e_cmd; /* ELF_C_* used at creation time */ + int e_fd; /* associated file descriptor */ + unsigned int e_flags; /* ELF_F_*, LIBELF_F_* flags */ + Elf_Kind e_kind; /* ELF_K_* */ + Elf *e_parent; /* non-NULL for archive members */ + char *e_rawfile; /* uninterpreted bytes */ + size_t e_rawsize; /* size of uninterpreted bytes */ + unsigned int e_version; /* file version */ + + union { + struct { /* ar(1) archives */ + off_t e_next; /* set by elf_rand()/elf_next() */ + int e_nchildren; + char *e_rawstrtab; /* file name strings */ + size_t e_rawstrtabsz; + char *e_rawsymtab; /* symbol table */ + size_t e_rawsymtabsz; + Elf_Arsym *e_symtab; + size_t e_symtabsz; + } e_ar; + struct { /* regular ELF files */ + union { + Elf32_Ehdr *e_ehdr32; + Elf64_Ehdr *e_ehdr64; + } e_ehdr; + union { + Elf32_Phdr *e_phdr32; + Elf64_Phdr *e_phdr64; + } e_phdr; + STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */ + size_t e_nphdr; /* number of Phdr entries */ + size_t e_nscn; /* number of sections */ + size_t e_strndx; /* string table section index */ + } e_elf; + } e_u; +}; + +struct _Elf_Scn { + union { + Elf32_Shdr s_shdr32; + Elf64_Shdr s_shdr64; + } s_shdr; + STAILQ_HEAD(, _Elf_Data) s_data; /* list of Elf_Data descriptors */ + STAILQ_HEAD(, _Elf_Data) s_rawdata; /* raw data for this section */ + STAILQ_ENTRY(_Elf_Scn) s_next; + struct _Elf *s_elf; /* parent ELF descriptor */ + unsigned int s_flags; /* flags for the section as a whole */ + size_t s_ndx; /* index# for this section */ + uint64_t s_offset; /* managed by elf_update() */ + uint64_t s_rawoff; /* original offset in the file */ + uint64_t s_size; /* managed by elf_update() */ +}; + + +enum { + ELF_TOFILE, + ELF_TOMEMORY +}; + +#define LIBELF_COPY_U32(DST,SRC,NAME) do { \ + if ((SRC)->NAME > UINT_MAX) { \ + LIBELF_SET_ERROR(RANGE, 0); \ + return (0); \ + } \ + (DST)->NAME = (SRC)->NAME; \ + } while (0) + +#define LIBELF_COPY_S32(DST,SRC,NAME) do { \ + if ((SRC)->NAME > INT_MAX || \ + (SRC)->NAME < INT_MIN) { \ + LIBELF_SET_ERROR(RANGE, 0); \ + return (0); \ + } \ + (DST)->NAME = (SRC)->NAME; \ + } while (0) + + +/* + * Prototypes + */ + +Elf_Data *_libelf_allocate_data(Elf_Scn *_s); +Elf *_libelf_allocate_elf(void); +Elf_Scn *_libelf_allocate_scn(Elf *_e, size_t _ndx); +Elf_Arhdr *_libelf_ar_gethdr(Elf *_e); +Elf *_libelf_ar_open(Elf *_e); +Elf *_libelf_ar_open_member(int _fd, Elf_Cmd _c, Elf *_ar); +Elf_Arsym *_libelf_ar_process_symtab(Elf *_ar, size_t *_dst); +unsigned long _libelf_checksum(Elf *_e, int _elfclass); +void *_libelf_ehdr(Elf *_e, int _elfclass, int _allocate); +int _libelf_falign(Elf_Type _t, int _elfclass); +size_t _libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version, + size_t count); +void (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass)) + (char *_dst, char *_src, size_t _cnt, int _byteswap); +void *_libelf_getphdr(Elf *_e, int _elfclass); +void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass); +void _libelf_init_elf(Elf *_e, Elf_Kind _kind); +int _libelf_malign(Elf_Type _t, int _elfclass); +size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version); +void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count); +Elf_Data *_libelf_release_data(Elf_Data *_d); +Elf *_libelf_release_elf(Elf *_e); +Elf_Scn *_libelf_release_scn(Elf_Scn *_s); +int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum); +int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum); +int _libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass, + size_t _shstrndx); +Elf_Data *_libelf_xlate(Elf_Data *_d, const Elf_Data *_s, + unsigned int _encoding, int _elfclass, int _direction); +int _libelf_xlate_shtype(uint32_t _sht); + +#endif /* __LIBELF_H_ */ diff --git a/simulators/gem5/ext/libelf/elf32.h b/simulators/gem5/ext/libelf/elf32.h new file mode 100644 index 00000000..d62de503 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf32.h @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf32.h,v 1.13 2006/10/17 05:43:30 jkoshy Exp $ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 32-bit architectures. + */ + +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; +typedef uint64_t Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/simulators/gem5/ext/libelf/elf64.h b/simulators/gem5/ext/libelf/elf64.h new file mode 100644 index 00000000..a59f3a09 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf64.h @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf64.h,v 1.17 2006/10/17 05:43:30 jkoshy Exp $ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/simulators/gem5/ext/libelf/elf_begin.c b/simulators/gem5/ext/libelf/elf_begin.c new file mode 100644 index 00000000..1b37aa06 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_begin.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include +#include +#include "libelf.h" + +#include "_libelf.h" + +static Elf * +_libelf_open_object(int fd, Elf_Cmd c) +{ + Elf *e; + void *m; + struct stat sb; + + /* + * 'Raw' files are always mapped with 'PROT_READ'. At + * elf_update(3) time for files opened with ELF_C_RDWR the + * mapping is unmapped, file data is written to using write(2) + * and then the raw data is immediately mapped back in. + */ + if (fstat(fd, &sb) < 0) { + LIBELF_SET_ERROR(IO, errno); + return (NULL); + } + + m = NULL; + if ((m = mmap(NULL, (size_t) sb.st_size, PROT_READ, MAP_PRIVATE, fd, + (off_t) 0)) == MAP_FAILED) { + LIBELF_SET_ERROR(IO, errno); + return (NULL); + } + + if ((e = elf_memory(m, (size_t) sb.st_size)) == NULL) { + (void) munmap(m, (size_t) sb.st_size); + return (NULL); + } + + e->e_flags |= LIBELF_F_MMAP; + e->e_fd = fd; + e->e_cmd = c; + + if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) { + (void) elf_end(e); + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + return (e); +} + +Elf * +elf_begin(int fd, Elf_Cmd c, Elf *a) +{ + Elf *e; + + e = NULL; + + if (LIBELF_PRIVATE(version) == EV_NONE) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + switch (c) { + case ELF_C_NULL: + return (NULL); + + case ELF_C_WRITE: + + if (a != NULL) { /* not allowed for ar(1) archives. */ + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + /* + * Check writeability of `fd' immediately and fail if + * not writeable. + */ + if (ftruncate(fd, (off_t) 0) < 0) { + LIBELF_SET_ERROR(IO, errno); + return (NULL); + } + + if ((e = _libelf_allocate_elf()) != NULL) { + _libelf_init_elf(e, ELF_K_ELF); + e->e_byteorder = LIBELF_PRIVATE(byteorder); + e->e_fd = fd; + e->e_cmd = c; + } + return (e); + + case ELF_C_RDWR: + if (a != NULL) { /* not allowed for ar(1) archives. */ + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + /*FALLTHROUGH*/ + case ELF_C_READ: + /* + * Descriptor `a' could be for a regular ELF file, or + * for an ar(1) archive. + */ + if (a && (a->e_fd != fd || c != a->e_cmd)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + break; + + default: + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + + } + + if (a == NULL) + e = _libelf_open_object(fd, c); + else if (a->e_kind == ELF_K_AR) + e = _libelf_ar_open_member(fd, c, a); + else + (e = a)->e_activations++; + + return (e); +} diff --git a/simulators/gem5/ext/libelf/elf_cntl.c b/simulators/gem5/ext/libelf/elf_cntl.c new file mode 100644 index 00000000..20b0af8c --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_cntl.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +int +elf_cntl(Elf *e, Elf_Cmd c) +{ + if (e == NULL || + (c != ELF_C_FDDONE && c != ELF_C_FDREAD)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (-1); + } + + if (e->e_parent) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (-1); + } + + if (c == ELF_C_FDREAD) { + if (e->e_cmd == ELF_C_WRITE) { + LIBELF_SET_ERROR(MODE, 0); + return (-1); + } + else + return (0); + } + + e->e_fd = -1; + return 0; +} diff --git a/simulators/gem5/ext/libelf/elf_common.h b/simulators/gem5/ext/libelf/elf_common.h new file mode 100644 index 00000000..c169e7e4 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_common.h @@ -0,0 +1,846 @@ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf_common.h,v 1.22 2007/04/03 01:47:07 kan Exp $ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +#include + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_SPARC64 11 /* SPARC 64-bit */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + terminationfunctions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', even == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/simulators/gem5/ext/libelf/elf_data.c b/simulators/gem5/ext/libelf/elf_data.c new file mode 100644 index 00000000..71e95750 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_data.c @@ -0,0 +1,222 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include "libelf.h" +#include + +#include "_libelf.h" + + +Elf_Data * +elf_getdata(Elf_Scn *s, Elf_Data *d) +{ + Elf *e; + char *dst; + size_t fsz, msz, count; + int elfclass, elftype; + unsigned int sh_type; + uint64_t sh_align, sh_offset, sh_size; + void (*xlate)(char *_d, char *_s, size_t _c, int _swap); + + if (s == NULL || (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF || + (d != NULL && s != d->d_scn)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL) + return (d); + + if (d != NULL) + return (STAILQ_NEXT(d, d_next)); + + if (e->e_rawfile == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + elfclass = e->e_class; + + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + + if (elfclass == ELFCLASS32) { + sh_type = s->s_shdr.s_shdr32.sh_type; + sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; + sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; + sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; + } else { + sh_type = s->s_shdr.s_shdr64.sh_type; + sh_offset = s->s_shdr.s_shdr64.sh_offset; + sh_size = s->s_shdr.s_shdr64.sh_size; + sh_align = s->s_shdr.s_shdr64.sh_addralign; + } + + if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || + elftype > ELF_T_LAST || + sh_offset + sh_size > (uint64_t) e->e_rawsize) { + LIBELF_SET_ERROR(SECTION, 0); + return (NULL); + } + + if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)(elftype, + (size_t) 1, e->e_version)) == 0) { + LIBELF_SET_ERROR(UNIMPL, 0); + return (NULL); + } + + + if (sh_size % fsz) { + LIBELF_SET_ERROR(SECTION, 0); + return (NULL); + } + + count = sh_size / fsz; + + msz = _libelf_msize(elftype, elfclass, e->e_version); + + assert(msz > 0); + + if ((dst = malloc(msz*count)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + if ((d = _libelf_allocate_data(s)) == NULL) + return (NULL); + + d->d_buf = dst; + d->d_off = 0; + d->d_align = sh_align; + d->d_size = msz * count; + d->d_type = elftype; + d->d_version = e->e_version; + + d->d_flags |= LIBELF_F_MALLOCED; + STAILQ_INSERT_TAIL(&s->s_data, d, d_next); + + xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass); + (*xlate)(d->d_buf, e->e_rawfile + sh_offset, count, e->e_byteorder != + LIBELF_PRIVATE(byteorder)); + + return (d); +} + +Elf_Data * +elf_newdata(Elf_Scn *s) +{ + Elf *e; + Elf_Data *d; + + if (s == NULL || (e = s->s_elf) == NULL || + e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + /* + * elf_newdata() has to append a data descriptor, so + * bring in existing section data if not already present. + */ + if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) + if (elf_getdata(s, NULL) == NULL) + return (NULL); + + if ((d = malloc(sizeof(Elf_Data))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return (NULL); + } + + STAILQ_INSERT_TAIL(&s->s_data, d, d_next); + d->d_flags = 0; + d->d_scn = s; + + d->d_align = 1; + d->d_buf = NULL; + d->d_off = (uint64_t) ~0; + d->d_size = 0; + d->d_type = ELF_T_BYTE; + d->d_version = LIBELF_PRIVATE(version); + + (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); + + return (d); +} + +/* + * Retrieve a data descriptor for raw (untranslated) data for section + * `s'. + */ + +Elf_Data * +elf_rawdata(Elf_Scn *s, Elf_Data *d) +{ + Elf *e; + int elf_class; + uint64_t sh_align, sh_offset, sh_size; + + if (s == NULL || (e = s->s_elf) == NULL || + e->e_kind != ELF_K_ELF || e->e_rawfile == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL) + return (d); + + if (d != NULL) + return (STAILQ_NEXT(d, d_next)); + + elf_class = e->e_class; + + assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64); + + if (elf_class == ELFCLASS32) { + sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; + sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; + sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; + } else { + sh_offset = s->s_shdr.s_shdr64.sh_offset; + sh_size = s->s_shdr.s_shdr64.sh_size; + sh_align = s->s_shdr.s_shdr64.sh_addralign; + } + + if ((d = _libelf_allocate_data(s)) == NULL) + return (NULL); + + d->d_buf = e->e_rawfile + sh_offset; + d->d_off = 0; + d->d_align = sh_align; + d->d_size = sh_size; + d->d_type = ELF_T_BYTE; + d->d_version = e->e_version; + + STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next); + + return (d); +} diff --git a/simulators/gem5/ext/libelf/elf_end.c b/simulators/gem5/ext/libelf/elf_end.c new file mode 100644 index 00000000..082ca2db --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_end.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include + +#include +#include "libelf.h" +#include + +#include "_libelf.h" + +int +elf_end(Elf *e) +{ + Elf *sv; + Elf_Scn *scn, *tscn; + + if (e == NULL || e->e_activations == 0) + return (0); + + if (--e->e_activations > 0) + return (e->e_activations); + + assert(e->e_activations == 0); + + while (e && e->e_activations == 0) { + switch (e->e_kind) { + case ELF_K_AR: + /* + * If we still have open child descriptors, we + * need to defer reclaiming resources till all + * the child descriptors for the archive are + * closed. + */ + if (e->e_u.e_ar.e_nchildren > 0) + return (0); + break; + case ELF_K_ELF: + /* + * Reclaim all section descriptors. + */ + STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) + scn = _libelf_release_scn(scn); + break; + case ELF_K_NUM: + assert(0); + default: + break; + } + + if (e->e_flags & LIBELF_F_MMAP) + (void) munmap(e->e_rawfile, e->e_rawsize); + + sv = e; + if ((e = e->e_parent) != NULL) + e->e_u.e_ar.e_nchildren--; + sv = _libelf_release_elf(sv); + } + + return (0); +} + diff --git a/simulators/gem5/ext/libelf/elf_errmsg.c b/simulators/gem5/ext/libelf/elf_errmsg.c new file mode 100644 index 00000000..5fafd5f5 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_errmsg.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include + +#include "_libelf.h" +#include "libelf.h" + +/* + * Retrieve a human readable translation for an error message. + */ + +const char *_libelf_errors[] = { +#define DEFINE_ERROR(N,S) [ELF_E_##N] = S + DEFINE_ERROR(NONE, "No Error"), + DEFINE_ERROR(ARCHIVE, "Malformed ar(1) archive"), + DEFINE_ERROR(ARGUMENT, "Invalid argument"), + DEFINE_ERROR(CLASS, "ELF class mismatch"), + DEFINE_ERROR(DATA, "Invalid data buffer descriptor"), + DEFINE_ERROR(HEADER, "Missing or malformed ELF header"), + DEFINE_ERROR(IO, "I/O error"), + DEFINE_ERROR(LAYOUT, "Layout constraint violation"), + DEFINE_ERROR(MODE, "Incorrect ELF descriptor mode"), + DEFINE_ERROR(RANGE, "Value out of range of target"), + DEFINE_ERROR(RESOURCE, "Resource exhaustion"), + DEFINE_ERROR(SECTION, "Invalid section descriptor"), + DEFINE_ERROR(SEQUENCE, "API calls out of sequence"), + DEFINE_ERROR(UNIMPL, "Unimplemented feature"), + DEFINE_ERROR(VERSION, "Unknown ELF API version"), + DEFINE_ERROR(NUM, "Unknown error") +#undef DEFINE_ERROR +}; + +const char * +elf_errmsg(int error) +{ + int oserr; + + if (error == 0 && (error = LIBELF_PRIVATE(error)) == 0) + return NULL; + else if (error == -1) + error = LIBELF_PRIVATE(error); + + oserr = error >> LIBELF_OS_ERROR_SHIFT; + error &= LIBELF_ELF_ERROR_MASK; + + if (error < 0 || error >= ELF_E_NUM) + return _libelf_errors[ELF_E_NUM]; + if (oserr) { + strncpy(LIBELF_PRIVATE(msg), _libelf_errors[error], + sizeof(LIBELF_PRIVATE(msg))); + strncat(LIBELF_PRIVATE(msg), ": ", sizeof(LIBELF_PRIVATE(msg))); + strncat(LIBELF_PRIVATE(msg), strerror(oserr), + sizeof(LIBELF_PRIVATE(msg))); + return (const char *)&LIBELF_PRIVATE(msg); + } + return _libelf_errors[error]; +} diff --git a/simulators/gem5/ext/libelf/elf_errno.c b/simulators/gem5/ext/libelf/elf_errno.c new file mode 100644 index 00000000..f860d1a8 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_errno.c @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +int +elf_errno(void) +{ + int old; + + old = LIBELF_PRIVATE(error); + LIBELF_PRIVATE(error) = 0; + return (old & LIBELF_ELF_ERROR_MASK); +} diff --git a/simulators/gem5/ext/libelf/elf_fill.c b/simulators/gem5/ext/libelf/elf_fill.c new file mode 100644 index 00000000..7d0ca63e --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_fill.c @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +void +elf_fill(int fill) +{ + LIBELF_PRIVATE(fillchar) = fill; +} diff --git a/simulators/gem5/ext/libelf/elf_flag.c b/simulators/gem5/ext/libelf/elf_flag.c new file mode 100644 index 00000000..234964b0 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_flag.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +unsigned int +elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags) +{ + Elf *e; + Elf_Scn *scn; + unsigned int r; + + if (d == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL || e->e_kind != ELF_K_ELF || + (flags & ~ELF_F_DIRTY) != 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (c == ELF_C_SET) + r = scn->s_flags |= flags; + else + r = scn->s_flags &= ~flags; + + return (r); +} + +unsigned int +elf_flagehdr(Elf *e, Elf_Cmd c, unsigned int flags) +{ + int ec; + void *ehdr; + + if (e == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) + ehdr = e->e_u.e_elf.e_ehdr.e_ehdr32; + else + ehdr = e->e_u.e_elf.e_ehdr.e_ehdr64; + + if (ehdr == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (0); + } + + return (elf_flagelf(e, c, flags)); +} + +unsigned int +elf_flagelf(Elf *e, Elf_Cmd c, unsigned int flags) +{ + int r; + + if (e == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (e->e_kind != ELF_K_ELF) || + (flags & ~(ELF_F_DIRTY|ELF_F_LAYOUT)) != 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (c == ELF_C_SET) + r = e->e_flags |= flags; + else + r = e->e_flags &= ~flags; + return (r); +} + +unsigned int +elf_flagphdr(Elf *e, Elf_Cmd c, unsigned int flags) +{ + int ec; + void *phdr; + + if (e == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) + phdr = e->e_u.e_elf.e_phdr.e_phdr32; + else + phdr = e->e_u.e_elf.e_phdr.e_phdr64; + + if (phdr == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (0); + } + + return (elf_flagelf(e, c, flags)); +} + +unsigned int +elf_flagscn(Elf_Scn *s, Elf_Cmd c, unsigned int flags) +{ + int r; + + if (s == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (flags & ~ELF_F_DIRTY) != 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (c == ELF_C_SET) + r = s->s_flags |= flags; + else + r = s->s_flags &= ~flags; + return (r); +} + +unsigned int +elf_flagshdr(Elf_Scn *s, Elf_Cmd c, unsigned int flags) +{ + return (elf_flagscn(s, c, flags)); +} diff --git a/simulators/gem5/ext/libelf/elf_getarhdr.c b/simulators/gem5/ext/libelf/elf_getarhdr.c new file mode 100644 index 00000000..e8456c29 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_getarhdr.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +Elf_Arhdr * +elf_getarhdr(Elf *e) +{ + Elf_Arhdr *arh; + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((arh = e->e_arhdr) != NULL) + return (arh); + + return (_libelf_ar_gethdr(e)); +} diff --git a/simulators/gem5/ext/libelf/elf_getarsym.c b/simulators/gem5/ext/libelf/elf_getarsym.c new file mode 100644 index 00000000..fc71decb --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_getarsym.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +Elf_Arsym * +elf_getarsym(Elf *ar, size_t *ptr) +{ + size_t n; + Elf_Arsym *symtab; + + n = 0; + symtab = NULL; + + if (ar == NULL || ar->e_kind != ELF_K_AR) + LIBELF_SET_ERROR(ARGUMENT, 0); + else if ((symtab = ar->e_u.e_ar.e_symtab) != NULL) + n = ar->e_u.e_ar.e_symtabsz; + else if (ar->e_u.e_ar.e_rawsymtab) + symtab = _libelf_ar_process_symtab(ar, &n); + else + LIBELF_SET_ERROR(ARCHIVE, 0); + + if (ptr) + *ptr = n; + return (symtab); +} + diff --git a/simulators/gem5/ext/libelf/elf_getbase.c b/simulators/gem5/ext/libelf/elf_getbase.c new file mode 100644 index 00000000..28f097aa --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_getbase.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +off_t +elf_getbase(Elf *e) +{ + if (e == NULL || + e->e_parent == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (off_t) -1; + } + + return ((off_t) ((uintptr_t) e->e_rawfile - + (uintptr_t) e->e_parent->e_rawfile)); +} diff --git a/simulators/gem5/ext/libelf/elf_getident.c b/simulators/gem5/ext/libelf/elf_getident.c new file mode 100644 index 00000000..41d09da2 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_getident.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include "libelf.h" + +#include "_libelf.h" + +char * +elf_getident(Elf *e, size_t *sz) +{ + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + goto error; + } + + if (e->e_cmd == ELF_C_WRITE && e->e_rawfile == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + goto error; + } + + assert(e->e_kind != ELF_K_AR || e->e_cmd == ELF_C_READ); + + if (sz) { + if (e->e_kind == ELF_K_AR) + *sz = SARMAG; + else if (e->e_kind == ELF_K_ELF) + *sz = EI_NIDENT; + else + *sz = e->e_rawsize; + } + + return (e->e_rawfile); + + error: + if (sz) + *sz = 0; + return (NULL); +} diff --git a/simulators/gem5/ext/libelf/elf_hash.c b/simulators/gem5/ext/libelf/elf_hash.c new file mode 100644 index 00000000..b2e4a0ac --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_hash.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +/* + * This elf_hash function is defined by the System V ABI. It must be + * kept compatible with "src/libexec/rtld-elf/rtld.c". + */ + +unsigned long +elf_hash(const char *name) +{ + unsigned long h, t; + const unsigned char *s; + + s = (const unsigned char *) name; + h = t = 0; + + for (; *s != '\0'; h = h & ~t) { + h = (h << 4) + *s++; + t = h & 0xF0000000UL; + if (t) + h ^= t >> 24; + } + + return (h); +} diff --git a/simulators/gem5/ext/libelf/elf_kind.c b/simulators/gem5/ext/libelf/elf_kind.c new file mode 100644 index 00000000..8f4b1b67 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_kind.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +Elf_Kind +elf_kind(Elf *e) +{ + if (e == NULL) + return (ELF_K_NONE); + if (e->e_kind == ELF_K_AR || + e->e_kind == ELF_K_ELF) + return (e->e_kind); + return (ELF_K_NONE); +} diff --git a/simulators/gem5/ext/libelf/elf_memory.c b/simulators/gem5/ext/libelf/elf_memory.c new file mode 100644 index 00000000..07c645ba --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_memory.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include "libelf.h" +#include + +#include "_libelf.h" + +Elf * +elf_memory(char *image, size_t sz) +{ + Elf *e; + + if (LIBELF_PRIVATE(version) == EV_NONE) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + if (image == NULL || sz == 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((e = _libelf_allocate_elf()) == NULL) + return (NULL); + + e->e_cmd = ELF_C_READ; + e->e_rawfile = image; + e->e_rawsize = sz; + +#undef LIBELF_IS_ELF +#define LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && \ + (P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 && \ + (P)[EI_MAG3] == ELFMAG3) + + if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) { + _libelf_init_elf(e, ELF_K_ELF); + e->e_class = image[EI_CLASS]; + e->e_byteorder = image[EI_DATA]; + e->e_version = image[EI_VERSION]; + + if (e->e_version > EV_CURRENT) { + e = _libelf_release_elf(e); + LIBELF_SET_ERROR(VERSION, 0); + return (NULL); + } + + if ((e->e_byteorder != ELFDATA2LSB && e->e_byteorder != + ELFDATA2MSB) || (e->e_class != ELFCLASS32 && e->e_class != + ELFCLASS64)) { + e = _libelf_release_elf(e); + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + } else if (sz >= SARMAG && + strncmp(image, ARMAG, (size_t) SARMAG) == 0) { + _libelf_init_elf(e, ELF_K_AR); + e = _libelf_ar_open(e); + } else + _libelf_init_elf(e, ELF_K_NONE); + + return (e); +} diff --git a/simulators/gem5/ext/libelf/elf_next.c b/simulators/gem5/ext/libelf/elf_next.c new file mode 100644 index 00000000..1b1c4090 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_next.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include "libelf.h" + +#include "_libelf.h" + +Elf_Cmd +elf_next(Elf *e) +{ + off_t next; + Elf *parent; + + if (e == NULL) + return (ELF_C_NULL); + + if ((parent = e->e_parent) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (ELF_C_NULL); + } + + assert (parent->e_kind == ELF_K_AR); + assert (parent->e_cmd == ELF_C_READ); + assert((uintptr_t) e->e_rawfile % 2 == 0); + assert(e->e_rawfile > parent->e_rawfile); + + next = e->e_rawfile - parent->e_rawfile + e->e_rawsize; + next = (next + 1) & ~1; /* round up to an even boundary */ + + parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ? (off_t) 0 : next; + + return (ELF_C_READ); +} diff --git a/simulators/gem5/ext/libelf/elf_phnum.c b/simulators/gem5/ext/libelf/elf_phnum.c new file mode 100644 index 00000000..0f0c5aa5 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_phnum.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include "libelf.h" + +#include "_libelf.h" + +int +elf_getphnum(Elf *e, size_t *phnum) +{ + void *eh; + int ec; + + if (e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + *phnum = e->e_u.e_elf.e_nphdr; + + return (1); +} diff --git a/simulators/gem5/ext/libelf/elf_queue.h b/simulators/gem5/ext/libelf/elf_queue.h new file mode 100644 index 00000000..37456ddb --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_queue.h @@ -0,0 +1,616 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.68 2006/10/24 11:20:29 ru Exp $ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ + } \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ + TRASHIT((elm)->field.stqe_next); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT((elm)->field.le_next); \ + TRASHIT((elm)->field.le_prev); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#ifdef __CC_SUPPORTS___INLINE + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !__CC_SUPPORTS___INLINE */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __CC_SUPPORTS___INLINE */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/simulators/gem5/ext/libelf/elf_rand.c b/simulators/gem5/ext/libelf/elf_rand.c new file mode 100644 index 00000000..ac44aea3 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_rand.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include "libelf.h" + +#include "_libelf.h" + +off_t +elf_rand(Elf *ar, off_t offset) +{ + struct ar_hdr *arh; + + if (ar == NULL || ar->e_kind != ELF_K_AR || + (offset & 1) || offset < SARMAG || + offset + sizeof(struct ar_hdr) >= ar->e_rawsize) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return 0; + } + + arh = (struct ar_hdr *) (ar->e_rawfile + offset); + + /* a too simple sanity check */ + if (arh->ar_fmag[0] != '`' || arh->ar_fmag[1] != '\n') { + LIBELF_SET_ERROR(ARCHIVE, 0); + return 0; + } + + ar->e_u.e_ar.e_next = offset; + + return (offset); +} diff --git a/simulators/gem5/ext/libelf/elf_rawfile.c b/simulators/gem5/ext/libelf/elf_rawfile.c new file mode 100644 index 00000000..d9262438 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_rawfile.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "libelf.h" + +#include "_libelf.h" + +char * +elf_rawfile(Elf *e, size_t *sz) +{ + char *ptr; + size_t size; + + size = e ? e->e_rawsize : 0; + ptr = NULL; + + if (e == NULL) + LIBELF_SET_ERROR(ARGUMENT, 0); + else if ((ptr = e->e_rawfile) == NULL && e->e_cmd == ELF_C_WRITE) + LIBELF_SET_ERROR(SEQUENCE, 0); + + if (sz) + *sz = size; + + return (ptr); +} diff --git a/simulators/gem5/ext/libelf/elf_scn.c b/simulators/gem5/ext/libelf/elf_scn.c new file mode 100644 index 00000000..cf596bac --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_scn.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include "gelf.h" +#include "libelf.h" +#include "_libelf.h" + +/* + * Load an ELF section table and create a list of Elf_Scn structures. + */ +static int +_libelf_load_scn(Elf *e, void *ehdr) +{ + int ec, swapbytes; + size_t fsz, i, shnum; + uint64_t shoff; + char *src; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + Elf_Scn *scn; + void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + + assert(e != NULL); + assert(ehdr != NULL); + assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0); + +#define CHECK_EHDR(E,EH) do { \ + if (fsz != (EH)->e_shentsize || \ + shoff + fsz * shnum > e->e_rawsize) { \ + LIBELF_SET_ERROR(HEADER, 0); \ + return (0); \ + } \ + } while (0) + + ec = e->e_class; + fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); + assert(fsz > 0); + + shnum = e->e_u.e_elf.e_nscn; + + if (ec == ELFCLASS32) { + eh32 = (Elf32_Ehdr *) ehdr; + shoff = (uint64_t) eh32->e_shoff; + CHECK_EHDR(e, eh32); + } else { + eh64 = (Elf64_Ehdr *) ehdr; + shoff = eh64->e_shoff; + CHECK_EHDR(e, eh64); + } + + xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); + + swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder); + src = e->e_rawfile + shoff; + + /* + * If the file is using extended numbering then section #0 + * would have already been read in. + */ + + i = 0; + if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { + assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) == + STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next)); + + i = 1; + src += fsz; + } + + for (; i < shnum; i++, src += fsz) { + if ((scn = _libelf_allocate_scn(e, i)) == NULL) + return (0); + + (*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes); + + if (ec == ELFCLASS32) { + scn->s_offset = scn->s_rawoff = + scn->s_shdr.s_shdr32.sh_offset; + scn->s_size = scn->s_shdr.s_shdr32.sh_size; + } else { + scn->s_offset = scn->s_rawoff = + scn->s_shdr.s_shdr64.sh_offset; + scn->s_size = scn->s_shdr.s_shdr64.sh_size; + } + } + + e->e_flags |= LIBELF_F_SHDRS_LOADED; + + return (1); +} + + +Elf_Scn * +elf_getscn(Elf *e, size_t index) +{ + int ec; + void *ehdr; + Elf_Scn *s; + + if (e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (NULL); + + if (e->e_cmd != ELF_C_WRITE && + (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && + _libelf_load_scn(e, ehdr) == 0) + return (NULL); + + STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) + if (s->s_ndx == index) + return (s); + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} + +size_t +elf_ndxscn(Elf_Scn *s) +{ + if (s == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (SHN_UNDEF); + } + return (s->s_ndx); +} + +Elf_Scn * +elf_newscn(Elf *e) +{ + int ec; + void *ehdr; + Elf_Scn *scn; + + if (e == NULL || e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { + LIBELF_SET_ERROR(CLASS, 0); + return (NULL); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (NULL); + + /* + * The application may be asking for a new section descriptor + * on an ELF object opened with ELF_C_RDWR or ELF_C_READ. We + * need to bring in the existing section information before + * appending a new one to the list. + * + * Per the ELF(3) API, an application is allowed to open a + * file using ELF_C_READ, mess with its internal structure and + * use elf_update(...,ELF_C_NULL) to compute its new layout. + */ + if (e->e_cmd != ELF_C_WRITE && + (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && + _libelf_load_scn(e, ehdr) == 0) + return (NULL); + + if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { + assert(e->e_u.e_elf.e_nscn == 0); + if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == + NULL) + return (NULL); + e->e_u.e_elf.e_nscn++; + } + + assert(e->e_u.e_elf.e_nscn > 0); + + if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL) + return (NULL); + + e->e_u.e_elf.e_nscn++; + + (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); + + return (scn); +} + +Elf_Scn * +elf_nextscn(Elf *e, Elf_Scn *s) +{ + if (e == NULL || (e->e_kind != ELF_K_ELF) || + (s && s->s_elf != e)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + return (s == NULL ? elf_getscn(e, (size_t) 1) : + STAILQ_NEXT(s, s_next)); +} diff --git a/simulators/gem5/ext/libelf/elf_shnum.c b/simulators/gem5/ext/libelf/elf_shnum.c new file mode 100644 index 00000000..adc77af0 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_shnum.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include "libelf.h" + +#include "_libelf.h" + +int +elf_getshnum(Elf *e, size_t *shnum) +{ + void *eh; + int ec; + + if (e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + *shnum = e->e_u.e_elf.e_nscn; + + return (1); +} diff --git a/simulators/gem5/ext/libelf/elf_shstrndx.c b/simulators/gem5/ext/libelf/elf_shstrndx.c new file mode 100644 index 00000000..5b9cccda --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_shstrndx.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include "libelf.h" + +#include "_libelf.h" + +int +elf_getshstrndx(Elf *e, size_t *strndx) +{ + void *eh; + int ec; + + if (e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + *strndx = e->e_u.e_elf.e_strndx; + + return (1); +} + +int +elf_setshstrndx(Elf *e, size_t strndx) +{ + void *eh; + int ec; + + if (e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || + ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + return (_libelf_setshstrndx(e, eh, ec, strndx)); +} diff --git a/simulators/gem5/ext/libelf/elf_strptr.c b/simulators/gem5/ext/libelf/elf_strptr.c new file mode 100644 index 00000000..6a05fa1d --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_strptr.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#ifdef __sun +#include +#endif + +#include +#include "gelf.h" + +#include "_libelf.h" + +/* + * Convert an ELF section#,offset pair to a string pointer. + */ + +char * +elf_strptr(Elf *e, size_t scndx, size_t offset) +{ + Elf_Scn *s; + Elf_Data *d; + size_t alignment, count; + GElf_Shdr shdr; + + if (e == NULL || e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((s = elf_getscn(e, scndx)) == NULL || + gelf_getshdr(s, &shdr) == NULL) + return (NULL); + + if (shdr.sh_type != SHT_STRTAB || + offset >= shdr.sh_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + d = NULL; + if (e->e_flags & ELF_F_LAYOUT) { + + /* + * The application is taking responsibility for the + * ELF object's layout, so we can directly translate + * an offset to a `char *' address using the `d_off' + * members of Elf_Data descriptors. + */ + while ((d = elf_getdata(s, d)) != NULL) { + + if (d->d_buf == 0 || d->d_size == 0) + continue; + + if (d->d_type != ELF_T_BYTE) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if (offset >= d->d_off && + offset < d->d_off + d->d_size) + return ((char *) d->d_buf + offset - d->d_off); + } + } else { + /* + * Otherwise, the `d_off' members are not useable and + * we need to compute offsets ourselves, taking into + * account 'holes' in coverage of the section introduced + * by alignment requirements. + */ + count = (size_t) 0; /* cumulative count of bytes seen */ + while ((d = elf_getdata(s, d)) != NULL && count <= offset) { + + if (d->d_buf == NULL || d->d_size == 0) + continue; + + if (d->d_type != ELF_T_BYTE) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((alignment = d->d_align) > 1) { + if ((alignment & (alignment - 1)) != 0) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + count = roundup(count, alignment); + } + + if (offset < count) { + /* offset starts in the 'hole' */ + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (offset < count + d->d_size) { + if (d->d_buf != NULL) + return ((char *) d->d_buf + + offset - count); + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + count += d->d_size; + } + } + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} diff --git a/simulators/gem5/ext/libelf/elf_types.m4 b/simulators/gem5/ext/libelf/elf_types.m4 new file mode 100644 index 00000000..a7292334 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_types.m4 @@ -0,0 +1,310 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/elf_types.m4,v 1.2 2006/12/18 05:40:01 jkoshy Exp $ + */ + +/* + * ELF types, defined in the "enum Elf_Type" API. + * + * The members of the list form a 3-tuple: (name, C-type-suffix, OSversion). + * + `name' is an Elf_Type symbol without the `ELF_T_' prefix. + * + `C-type-suffix' is the suffix for Elf32_ and Elf64_ type names. + * + `version' is the OS version the symbol first appeared in. + * + */ + +define(`ELF_TYPE_LIST', + ``ADDR, Addr, 600102', + `BYTE, Byte, 600102', + `CAP, Cap, 700025', + `DYN, Dyn, 600102', + `EHDR, Ehdr, 600102', + `HALF, Half, 600102', + `LWORD, Lword, 700025', + `MOVE, Move, 700025', + `MOVEP, MoveP, 700025', + `NOTE, Note, 600102', + `OFF, Off, 600102', + `PHDR, Phdr, 600102', + `REL, Rel, 600102', + `RELA, Rela, 600102', + `SHDR, Shdr, 600102', + `SWORD, Sword, 600102', + `SXWORD, Sxword, 700009', + `SYMINFO, Syminfo, 700025', + `SYM, Sym, 600102', + `VDEF, Verdef, 700009', + `VNEED, Verneed, 700009', + `WORD, Word, 600102', + `XWORD, Xword, 700009', + `NUM, _, _'') + +/* + * DEFINE_STRUCT(NAME,MEMBERLIST...) + * + * Map a type name to its members. + * + * Each member-list element comprises of pairs of (field name, type), + * in the sequence used in the file representation of `NAME'. + * + * Each member list element comprises a pair containing a field name + * and a basic type. Basic types include IDENT, HALF, WORD, LWORD, + * ADDR{32,64}, OFF{32,64}, SWORD, XWORD, SXWORD. + * + * The last element of a member list is the null element: `_,_'. + */ + +define(`DEFINE_STRUCT',`define(`$1_DEF',shift($@))dnl') + +DEFINE_STRUCT(`Elf32_Cap', + ``c_tag, WORD', + `c_un.c_val, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Cap', + ``c_tag, XWORD', + `c_un.c_val, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Dyn', + ``d_tag, SWORD', + `d_un.d_ptr, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Dyn', + ``d_tag, SXWORD', + `d_un.d_ptr, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Ehdr', + ``e_ident, IDENT', + `e_type, HALF', + `e_machine, HALF', + `e_version, WORD', + `e_entry, ADDR', + `e_phoff, OFF', + `e_shoff, OFF', + `e_flags, WORD', + `e_ehsize, HALF', + `e_phentsize, HALF', + `e_phnum, HALF', + `e_shentsize, HALF', + `e_shnum, HALF', + `e_shstrndx, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Ehdr', + ``e_ident, IDENT', + `e_type, HALF', + `e_machine, HALF', + `e_version, WORD', + `e_entry, ADDR', + `e_phoff, OFF', + `e_shoff, OFF', + `e_flags, WORD', + `e_ehsize, HALF', + `e_phentsize, HALF', + `e_phnum, HALF', + `e_shentsize, HALF', + `e_shnum, HALF', + `e_shstrndx, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf32_Move', + ``m_value, LWORD', + `m_info, WORD', + `m_poffset, WORD', + `m_repeat, HALF', + `m_stride, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Move', + ``m_value, LWORD', + `m_info, XWORD', + `m_poffset, XWORD', + `m_repeat, HALF', + `m_stride, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf32_Phdr', + ``p_type, WORD', + `p_offset, OFF', + `p_vaddr, ADDR', + `p_paddr, ADDR', + `p_filesz, WORD', + `p_memsz, WORD', + `p_flags, WORD', + `p_align, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Phdr', + ``p_type, WORD', + `p_flags, WORD', + `p_offset, OFF', + `p_vaddr, ADDR', + `p_paddr, ADDR', + `p_filesz, XWORD', + `p_memsz, XWORD', + `p_align, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Rel', + ``r_offset, ADDR', + `r_info, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Rel', + ``r_offset, ADDR', + `r_info, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Rela', + ``r_offset, ADDR', + `r_info, WORD', + `r_addend, SWORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Rela', + ``r_offset, ADDR', + `r_info, XWORD', + `r_addend, SXWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Shdr', + ``sh_name, WORD', + `sh_type, WORD', + `sh_flags, WORD', + `sh_addr, ADDR', + `sh_offset, OFF', + `sh_size, WORD', + `sh_link, WORD', + `sh_info, WORD', + `sh_addralign, WORD', + `sh_entsize, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Shdr', + ``sh_name, WORD', + `sh_type, WORD', + `sh_flags, XWORD', + `sh_addr, ADDR', + `sh_offset, OFF', + `sh_size, XWORD', + `sh_link, WORD', + `sh_info, WORD', + `sh_addralign, XWORD', + `sh_entsize, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Sym', + ``st_name, WORD', + `st_value, ADDR', + `st_size, WORD', + `st_info, BYTE', + `st_other, BYTE', + `st_shndx, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Sym', + ``st_name, WORD', + `st_info, BYTE', + `st_other, BYTE', + `st_shndx, HALF', + `st_value, ADDR', + `st_size, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Syminfo', + ``si_boundto, HALF', + `si_flags, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Syminfo', + ``si_boundto, HALF', + `si_flags, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf32_Verdaux', + ``vda_name, WORD', + `vda_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Verdaux', + ``vda_name, WORD', + `vda_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Verdef', + ``vd_version, HALF', + `vd_flags, HALF', + `vd_ndx, HALF', + `vd_cnt, HALF', + `vd_hash, WORD', + `vd_aux, WORD', + `vd_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Verdef', + ``vd_version, HALF', + `vd_flags, HALF', + `vd_ndx, HALF', + `vd_cnt, HALF', + `vd_hash, WORD', + `vd_aux, WORD', + `vd_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Verneed', + ``vn_version, HALF', + `vn_cnt, HALF', + `vn_file, WORD', + `vn_aux, WORD', + `vn_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Verneed', + ``vn_version, HALF', + `vn_cnt, HALF', + `vn_file, WORD', + `vn_aux, WORD', + `vn_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Vernaux', + ``vna_hash, WORD', + `vna_flags, HALF', + `vna_other, HALF', + `vna_name, WORD', + `vna_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Vernaux', + ``vna_hash, WORD', + `vna_flags, HALF', + `vna_other, HALF', + `vna_name, WORD', + `vna_next, WORD', + `_,_'') diff --git a/simulators/gem5/ext/libelf/elf_update.c b/simulators/gem5/ext/libelf/elf_update.c new file mode 100644 index 00000000..6959d3c3 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_update.c @@ -0,0 +1,885 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#ifdef __sun +#include +#endif + +#include +#include +#include "gelf.h" +#include "libelf.h" +#include +#include +#include + +#include "_libelf.h" + +/* + * Update the internal data structures associated with an ELF object. + * Returns the size in bytes the ELF object would occupy in its file + * representation. + * + * After a successful call to this function, the following structures + * are updated: + * + * - The ELF header is updated. + * - All sections are sorted in order of ascending addresses and their + * section header table entries updated. An error is signalled + * if an overlap was detected among sections. + * - All data descriptors associated with a section are sorted in order + * of ascending addresses. Overlaps, if detected, are signalled as + * errors. Other sanity checks for alignments, section types etc. are + * made. + * + * After a resync_elf() successfully returns, the ELF descriptor is + * ready for being handed over to _libelf_write_elf(). + * + * File alignments: + * PHDR - Addr + * SHDR - Addr + * + * XXX: how do we handle 'flags'. + */ + +/* + * Compute the extents of a section, by looking at the. + */ +static int +_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) +{ + int ec; + Elf_Data *d, *td; + unsigned int elftype; + uint32_t sh_type; + uint64_t d_align; + uint64_t sh_align, sh_entsize, sh_offset, sh_size; + uint64_t scn_size, scn_alignment; + + /* + * We need to recompute library private data structures if one + * or more of the following is true: + * - The underlying Shdr structure has been marked `dirty'. Significant + * fields include: `sh_offset', `sh_type', `sh_size', `sh_addralign'. + * - The Elf_Data structures part of this section have been marked + * `dirty'. Affected members include `d_align', `d_offset', `d_type', + * and `d_size'. + * - The section as a whole is `dirty', e.g., it has been allocated + * using elf_newscn(), or if a new Elf_Data structure was added using + * elf_newdata(). + * + * Each of these conditions would result in the ELF_F_DIRTY bit being + * set on the section descriptor's `s_flags' field. + */ + + ec = e->e_class; + + if (ec == ELFCLASS32) { + sh_type = s->s_shdr.s_shdr32.sh_type; + sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; + sh_entsize = (uint64_t) s->s_shdr.s_shdr32.sh_entsize; + sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; + sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; + } else { + sh_type = s->s_shdr.s_shdr64.sh_type; + sh_align = s->s_shdr.s_shdr64.sh_addralign; + sh_entsize = s->s_shdr.s_shdr64.sh_entsize; + sh_offset = s->s_shdr.s_shdr64.sh_offset; + sh_size = s->s_shdr.s_shdr64.sh_size; + } + + if (sh_type == SHT_NULL || sh_type == SHT_NOBITS) + return (1); + + if ((s->s_flags & ELF_F_DIRTY) == 0) { + if ((size_t) *rc < sh_offset + sh_size) + *rc = sh_offset + sh_size; + return (1); + } + + elftype = _libelf_xlate_shtype(sh_type); + if (elftype > ELF_T_LAST) { + LIBELF_SET_ERROR(SECTION, 0); + return (0); + } + + /* + * Compute the extent of the data descriptors associated with + * this section. + */ + scn_alignment = 0; + if (sh_align == 0) + sh_align = _libelf_falign(elftype, ec); + + /* Compute the section alignment. */ + STAILQ_FOREACH(d, &s->s_data, d_next) { + if (d->d_type != elftype) { + LIBELF_SET_ERROR(DATA, 0); + return (0); + } + if (d->d_version != e->e_version) { + LIBELF_SET_ERROR(VERSION, 0); + return (0); + } + if ((d_align = d->d_align) % sh_align) { + LIBELF_SET_ERROR(LAYOUT, 0); + return (0); + } + if (d_align == 0 || (d_align & (d_align - 1))) { + LIBELF_SET_ERROR(DATA, 0); + return (0); + } + if (d_align > scn_alignment) + scn_alignment = d_align; + } + + scn_size = 0L; + + STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { + if (e->e_flags & ELF_F_LAYOUT) { + if ((uint64_t) d->d_off + d->d_size > scn_size) + scn_size = d->d_off + d->d_size; + } else { + scn_size = roundup(scn_size, scn_alignment); + d->d_off = scn_size; + scn_size += d->d_size; + } + } + + /* + * If the application is requesting full control over the layout + * of the section, check its values for sanity. + */ + if (e->e_flags & ELF_F_LAYOUT) { + if (scn_alignment > sh_align || sh_offset % sh_align || + sh_size < scn_size) { + LIBELF_SET_ERROR(LAYOUT, 0); + return (0); + } + } else { + /* + * Otherwise compute the values in the section header. + */ + + if (scn_alignment > sh_align) + sh_align = scn_alignment; + + /* + * If the section entry size is zero, try and fill in an + * appropriate entry size. Per the elf(5) manual page + * sections without fixed-size entries should have their + * 'sh_entsize' field set to zero. + */ + if (sh_entsize == 0 && + (sh_entsize = _libelf_fsize(elftype, ec, e->e_version, + (size_t) 1)) == 1) + sh_entsize = 0; + + sh_size = scn_size; + sh_offset = roundup(*rc, sh_align); + + if (ec == ELFCLASS32) { + s->s_shdr.s_shdr32.sh_addralign = (uint32_t) sh_align; + s->s_shdr.s_shdr32.sh_entsize = (uint32_t) sh_entsize; + s->s_shdr.s_shdr32.sh_offset = (uint32_t) sh_offset; + s->s_shdr.s_shdr32.sh_size = (uint32_t) sh_size; + } else { + s->s_shdr.s_shdr64.sh_addralign = sh_align; + s->s_shdr.s_shdr64.sh_entsize = sh_entsize; + s->s_shdr.s_shdr64.sh_offset = sh_offset; + s->s_shdr.s_shdr64.sh_size = sh_size; + } + } + + if ((size_t) *rc < sh_offset + sh_size) + *rc = sh_offset + sh_size; + + s->s_size = sh_size; + s->s_offset = sh_offset; + return (1); +} + + +/* + * Insert a section in ascending order in the list + */ + +static int +_libelf_insert_section(Elf *e, Elf_Scn *s) +{ + Elf_Scn *t, *prevt; + uint64_t smax, smin, tmax, tmin; + + smin = s->s_offset; + smax = smin + s->s_size; + + prevt = NULL; + STAILQ_FOREACH(t, &e->e_u.e_elf.e_scn, s_next) { + tmin = t->s_offset; + tmax = tmin + t->s_size; + + /* check if there is an overlap */ + if (tmax < smin) { + prevt = t; + continue; + } else if (smax < tmin) + break; + else { + LIBELF_SET_ERROR(LAYOUT, 0); + return (0); + } + } + + if (prevt) + STAILQ_INSERT_AFTER(&e->e_u.e_elf.e_scn, prevt, s, s_next); + else + STAILQ_INSERT_HEAD(&e->e_u.e_elf.e_scn, s, s_next); + return (1); +} + +static off_t +_libelf_resync_sections(Elf *e, off_t rc) +{ + int ec; + off_t nrc; + size_t sh_type; + Elf_Scn *s, *ts; + + ec = e->e_class; + + /* + * Make a pass through sections, computing the extent of each + * section. Order in increasing order of addresses. + */ + + nrc = rc; + STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) + if (_libelf_compute_section_extents(e, s, &nrc) == 0) + return ((off_t) -1); + + STAILQ_FOREACH_SAFE(s, &e->e_u.e_elf.e_scn, s_next, ts) { + if (ec == ELFCLASS32) + sh_type = s->s_shdr.s_shdr32.sh_type; + else + sh_type = s->s_shdr.s_shdr64.sh_type; + + /* XXX Do we need the 'size' field of an SHT_NOBITS section */ + if (sh_type == SHT_NOBITS || sh_type == SHT_NULL) + continue; + + if (s->s_offset < (uint64_t) rc) { + if (s->s_offset + s->s_size < (uint64_t) rc) { + /* + * Try insert this section in the + * correct place in the list, + * detecting overlaps if any. + */ + STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, + s_next); + if (_libelf_insert_section(e, s) == 0) + return ((off_t) -1); + } else { + LIBELF_SET_ERROR(LAYOUT, 0); + return ((off_t) -1); + } + } else + rc = s->s_offset + s->s_size; + } + + assert(nrc == rc); + + return (rc); +} + +static off_t +_libelf_resync_elf(Elf *e) +{ + int ec, eh_class, eh_type; + unsigned int eh_byteorder, eh_version; + size_t align, fsz; + size_t phnum, shnum; + off_t rc, phoff, shoff; + void *ehdr; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + rc = 0; + + ec = e->e_class; + + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + /* + * Prepare the EHDR. + */ + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return ((off_t) -1); + + eh32 = ehdr; + eh64 = ehdr; + + if (ec == ELFCLASS32) { + eh_byteorder = eh32->e_ident[EI_DATA]; + eh_class = eh32->e_ident[EI_CLASS]; + phoff = (uint64_t) eh32->e_phoff; + shoff = (uint64_t) eh32->e_shoff; + eh_type = eh32->e_type; + eh_version = eh32->e_version; + } else { + eh_byteorder = eh64->e_ident[EI_DATA]; + eh_class = eh64->e_ident[EI_CLASS]; + phoff = eh64->e_phoff; + shoff = eh64->e_shoff; + eh_type = eh64->e_type; + eh_version = eh64->e_version; + } + + if (eh_version == EV_NONE) + eh_version = EV_CURRENT; + + if (eh_version != e->e_version) { /* always EV_CURRENT */ + LIBELF_SET_ERROR(VERSION, 0); + return ((off_t) -1); + } + + if (eh_class != e->e_class) { + LIBELF_SET_ERROR(CLASS, 0); + return ((off_t) -1); + } + + if (e->e_cmd != ELF_C_WRITE && eh_byteorder != e->e_byteorder) { + LIBELF_SET_ERROR(HEADER, 0); + return ((off_t) -1); + } + + shnum = e->e_u.e_elf.e_nscn; + phnum = e->e_u.e_elf.e_nphdr; + + e->e_byteorder = eh_byteorder; + +#define INITIALIZE_EHDR(E,EC,V) do { \ + (E)->e_ident[EI_MAG0] = ELFMAG0; \ + (E)->e_ident[EI_MAG1] = ELFMAG1; \ + (E)->e_ident[EI_MAG2] = ELFMAG2; \ + (E)->e_ident[EI_MAG3] = ELFMAG3; \ + (E)->e_ident[EI_CLASS] = (EC); \ + (E)->e_ident[EI_VERSION] = (V); \ + (E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V), \ + (size_t) 1); \ + (E)->e_phentsize = _libelf_fsize(ELF_T_PHDR, (EC), (V), \ + (size_t) 1); \ + (E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V), \ + (size_t) 1); \ + } while (0) + + if (ec == ELFCLASS32) + INITIALIZE_EHDR(eh32, ec, eh_version); + else + INITIALIZE_EHDR(eh64, ec, eh_version); + + (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); + + rc += _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1); + + /* + * Compute the layout the program header table, if one is + * present. The program header table needs to be aligned to a + * `natural' boundary. + */ + if (phnum) { + fsz = _libelf_fsize(ELF_T_PHDR, ec, eh_version, phnum); + align = _libelf_falign(ELF_T_PHDR, ec); + + if (e->e_flags & ELF_F_LAYOUT) { + /* + * Check offsets for sanity. + */ + if (rc > phoff) { + LIBELF_SET_ERROR(HEADER, 0); + return ((off_t) -1); + } + + if (phoff % align) { + LIBELF_SET_ERROR(LAYOUT, 0); + return ((off_t) -1); + } + + } else + phoff = roundup(rc, align); + + rc = phoff + fsz; + } else + phoff = 0; + + /* + * Compute the layout of the sections associated with the + * file. + */ + + if ((rc = _libelf_resync_sections(e, rc)) < 0) + return ((off_t) -1); + + /* + * Compute the space taken up by the section header table, if + * one is needed. + */ + if (shnum) { + fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, (size_t) 1); + align = _libelf_falign(ELF_T_SHDR, ec); + + if (e->e_flags & ELF_F_LAYOUT) { + if (rc > shoff) { + LIBELF_SET_ERROR(HEADER, 0); + return ((off_t) -1); + } + + if (shoff % align) { + LIBELF_SET_ERROR(LAYOUT, 0); + return ((off_t) -1); + } + } else + shoff = roundup(rc, align); + + rc = shoff + fsz * shnum; + } else + shoff = 0; + + /* + * Set the fields of the Executable Header that could potentially use + * extended numbering. + */ + _libelf_setphnum(e, ehdr, ec, phnum); + _libelf_setshnum(e, ehdr, ec, shnum); + + /* + * Update the `e_phoff' and `e_shoff' fields if the library is + * doing the layout. + */ + if ((e->e_flags & ELF_F_LAYOUT) == 0) { + if (ec == ELFCLASS32) { + eh32->e_phoff = (uint32_t) phoff; + eh32->e_shoff = (uint32_t) shoff; + } else { + eh64->e_phoff = (uint64_t) phoff; + eh64->e_shoff = (uint64_t) shoff; + } + } + + return (rc); +} + +/* + * Write out the contents of a section. + */ + +static off_t +_libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc) +{ + int ec; + size_t fsz, msz, nobjects; + uint32_t sh_type; + uint64_t sh_off; + int elftype; + Elf_Data *d, dst; + + if ((ec = e->e_class) == ELFCLASS32) + sh_type = s->s_shdr.s_shdr32.sh_type; + else + sh_type = s->s_shdr.s_shdr64.sh_type; + + /* + * Ignore sections that do not allocate space in the file. + */ + if (sh_type == SHT_NOBITS || sh_type == SHT_NULL) + return (rc); + + + elftype = _libelf_xlate_shtype(sh_type); + assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST); + + msz = _libelf_msize(elftype, ec, e->e_version); + + sh_off = s->s_offset; + assert(sh_off % _libelf_falign(elftype, ec) == 0); + + /* + * If the section has a `rawdata' descriptor, and the section + * contents have not been modified, use its contents directly. + * The `s_rawoff' member contains the offset into the original + * file, while `s_offset' contains its new location in the + * destination. + */ + + if (STAILQ_EMPTY(&s->s_data)) { + + if ((d = elf_rawdata(s, NULL)) == NULL) + return ((off_t) -1); + + STAILQ_FOREACH(d, &s->s_rawdata, d_next) { + if ((uint64_t) rc < sh_off + d->d_off) + (void) memset(nf + rc, + LIBELF_PRIVATE(fillchar), sh_off + + d->d_off - rc); + rc = sh_off + d->d_off; + + assert(d->d_buf != NULL); + assert(d->d_type == ELF_T_BYTE); + assert(d->d_version == e->e_version); + + (void) memcpy(nf + rc, + e->e_rawfile + s->s_rawoff + d->d_off, d->d_size); + + rc += d->d_size; + } + + return (rc); + } + + /* + * Iterate over the set of data descriptors for this section. + * The prior call to _libelf_resync_elf() would have setup the + * descriptors for this step. + */ + + dst.d_version = e->e_version; + + STAILQ_FOREACH(d, &s->s_data, d_next) { + + if ((uint64_t) rc < sh_off + d->d_off) + (void) memset(nf + rc, + LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc); + + rc = sh_off + d->d_off; + + assert(d->d_buf != NULL); + assert(d->d_type == (Elf_Type) elftype); + assert(d->d_version == e->e_version); + assert(d->d_size % msz == 0); + + nobjects = d->d_size / msz; + + fsz = _libelf_fsize(elftype, ec, e->e_version, nobjects); + + dst.d_buf = nf + rc; + dst.d_size = fsz; + + if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) == + NULL) + return ((off_t) -1); + + rc += fsz; + } + + return ((off_t) rc); +} + +/* + * Write out the file image. + * + * The original file could have been mapped in with an ELF_C_RDWR + * command and the application could have added new content or + * re-arranged its sections before calling elf_update(). Consequently + * its not safe to work `in place' on the original file. So we + * malloc() the required space for the updated ELF object and build + * the object there and write it out to the underlying file at the + * end. Note that the application may have opened the underlying file + * in ELF_C_RDWR and only retrieved/modified a few sections. We take + * care to avoid translating file sections unnecessarily. + * + * Gaps in the coverage of the file by the file's sections will be + * filled with the fill character set by elf_fill(3). + */ + +static off_t +_libelf_write_elf(Elf *e, off_t newsize) +{ + int ec; + off_t rc; + size_t fsz, msz, phnum, shnum; + uint64_t phoff, shoff; + void *ehdr; + char *newfile; + Elf_Data dst, src; + Elf_Scn *scn, *tscn; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + assert(e->e_kind == ELF_K_ELF); + assert(e->e_cmd != ELF_C_READ); + assert(e->e_fd >= 0); + + if ((newfile = malloc((size_t) newsize)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return ((off_t) -1); + } + + ec = e->e_class; + + ehdr = _libelf_ehdr(e, ec, 0); + assert(ehdr != NULL); + + phnum = e->e_u.e_elf.e_nphdr; + + if (ec == ELFCLASS32) { + eh32 = (Elf32_Ehdr *) ehdr; + + phoff = (uint64_t) eh32->e_phoff; + shnum = eh32->e_shnum; + shoff = (uint64_t) eh32->e_shoff; + } else { + eh64 = (Elf64_Ehdr *) ehdr; + + phoff = eh64->e_phoff; + shnum = eh64->e_shnum; + shoff = eh64->e_shoff; + } + + fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); + msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version); + + (void) memset(&dst, 0, sizeof(dst)); + (void) memset(&src, 0, sizeof(src)); + + src.d_buf = ehdr; + src.d_size = msz; + src.d_type = ELF_T_EHDR; + src.d_version = dst.d_version = e->e_version; + + rc = 0; + + dst.d_buf = newfile + rc; + dst.d_size = fsz; + + if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) == + NULL) + goto error; + + rc += fsz; + + /* + * Write the program header table if present. + */ + + if (phnum != 0 && phoff != 0) { + assert((unsigned) rc <= phoff); + + fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum); + + assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0); + assert(fsz > 0); + + src.d_version = dst.d_version = e->e_version; + src.d_type = ELF_T_PHDR; + + if (ec == ELFCLASS32) + src.d_buf = e->e_u.e_elf.e_phdr.e_phdr32; + else + src.d_buf = e->e_u.e_elf.e_phdr.e_phdr64; + + src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec, + e->e_version); + + dst.d_size = fsz; + + if ((uint64_t) rc < phoff) + (void) memset(newfile + rc, + LIBELF_PRIVATE(fillchar), phoff - rc); + + dst.d_buf = newfile + rc; + + if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) == + NULL) + goto error; + + rc = phoff + fsz; + } + + /* + * Write out individual sections. + */ + + STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) + if ((rc = _libelf_write_scn(e, newfile, scn, rc)) < 0) + goto error; + + /* + * Write out the section header table, if required. + */ + + if (shnum != 0 && shoff != 0) { + assert((unsigned) rc <= shoff); + + if ((uint64_t) rc < shoff) + (void) memset(newfile + rc, + LIBELF_PRIVATE(fillchar), shoff - rc); + + rc = shoff; + + assert(rc % _libelf_falign(ELF_T_SHDR, ec) == 0); + + src.d_type = ELF_T_SHDR; + src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version); + src.d_version = dst.d_version = e->e_version; + + fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); + + STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) { + if (ec == ELFCLASS32) + src.d_buf = &scn->s_shdr.s_shdr32; + else + src.d_buf = &scn->s_shdr.s_shdr64; + + dst.d_size = fsz; + dst.d_buf = newfile + rc; + + if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, + ELF_TOFILE) != &dst) + goto error; + + rc += fsz; + } + } + + /* + */ + + assert(rc == newsize); + + /* + * Write out the constructed contents and remap the file in + * read-only. + */ + + if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) { + LIBELF_SET_ERROR(IO, errno); + goto error; + } + + if (write(e->e_fd, newfile, (size_t) newsize) != newsize || + lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) { + LIBELF_SET_ERROR(IO, errno); + goto error; + } + + if (e->e_cmd != ELF_C_WRITE) { + if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ, + MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) { + LIBELF_SET_ERROR(IO, errno); + goto error; + } + e->e_rawsize = newsize; + } + + /* + * Reset flags, remove existing section descriptors and + * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr() + * and elf_getscn() will function correctly. + */ + + e->e_flags &= ~ELF_F_DIRTY; + + STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) + _libelf_release_scn(scn); + + if (ec == ELFCLASS32) { + free(e->e_u.e_elf.e_ehdr.e_ehdr32); + if (e->e_u.e_elf.e_phdr.e_phdr32) + free(e->e_u.e_elf.e_phdr.e_phdr32); + + e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL; + e->e_u.e_elf.e_phdr.e_phdr32 = NULL; + } else { + free(e->e_u.e_elf.e_ehdr.e_ehdr64); + if (e->e_u.e_elf.e_phdr.e_phdr64) + free(e->e_u.e_elf.e_phdr.e_phdr64); + + e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL; + e->e_u.e_elf.e_phdr.e_phdr64 = NULL; + } + + return (rc); + + error: + if (newfile) + free(newfile); + return ((off_t) -1); +} + +off_t +elf_update(Elf *e, Elf_Cmd c) +{ + int ec; + off_t rc; + + rc = (off_t) -1; + + if (e == NULL || e->e_kind != ELF_K_ELF || + (c != ELF_C_NULL && c != ELF_C_WRITE)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (rc); + } + + if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { + LIBELF_SET_ERROR(CLASS, 0); + return (rc); + } + + if (e->e_version == EV_NONE) + e->e_version = EV_CURRENT; + + if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (rc); + } + + if ((rc = _libelf_resync_elf(e)) < 0) + return (rc); + + if (c == ELF_C_NULL) + return (rc); + + if (e->e_cmd == ELF_C_READ) { + /* + * This descriptor was opened in read-only mode or by + * elf_memory(). + */ + if (e->e_fd) + LIBELF_SET_ERROR(MODE, 0); + else + LIBELF_SET_ERROR(ARGUMENT, 0); + return ((off_t) -1); + } + + if (e->e_fd < 0) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return ((off_t) -1); + } + + return (_libelf_write_elf(e, rc)); +} diff --git a/simulators/gem5/ext/libelf/elf_version.c b/simulators/gem5/ext/libelf/elf_version.c new file mode 100644 index 00000000..e4c1e7d3 --- /dev/null +++ b/simulators/gem5/ext/libelf/elf_version.c @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "libelf.h" +#include "_libelf.h" + +unsigned int +elf_version(unsigned int v) +{ + unsigned int old; + + if ((old = LIBELF_PRIVATE(version)) == EV_NONE) + old = EV_CURRENT; + + if (v == EV_NONE) + return old; + if (v > EV_CURRENT) { + LIBELF_SET_ERROR(VERSION, 0); + return EV_NONE; + } + + LIBELF_PRIVATE(version) = v; + return (old); +} diff --git a/simulators/gem5/ext/libelf/gelf.h b/simulators/gem5/ext/libelf/gelf.h new file mode 100644 index 00000000..6ccb87f9 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf.h @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/gelf.h,v 1.3 2007/03/08 04:01:30 jkoshy Exp $ + */ + +#ifndef _GELF_H_ +#define _GELF_H_ + + +#include "libelf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef Elf64_Addr GElf_Addr; /* Addresses */ +typedef Elf64_Half GElf_Half; /* Half words (16 bit) */ +typedef Elf64_Off GElf_Off; /* Offsets */ +typedef Elf64_Sword GElf_Sword; /* Signed words (32 bit) */ +typedef Elf64_Sxword GElf_Sxword; /* Signed long words (64 bit) */ +typedef Elf64_Word GElf_Word; /* Unsigned words (32 bit) */ +typedef Elf64_Xword GElf_Xword; /* Unsigned long words (64 bit) */ + +typedef Elf64_Dyn GElf_Dyn; /* ".dynamic" section entries */ +typedef Elf64_Ehdr GElf_Ehdr; /* ELF header */ +typedef Elf64_Phdr GElf_Phdr; /* Program header */ +typedef Elf64_Shdr GElf_Shdr; /* Section header */ +typedef Elf64_Sym GElf_Sym; /* Symbol table entries */ +typedef Elf64_Rel GElf_Rel; /* Relocation entries */ +typedef Elf64_Rela GElf_Rela; /* Relocation entries with addend */ + +typedef Elf64_Cap GElf_Cap; /* SW/HW capabilities */ +typedef Elf64_Move GElf_Move; /* Move entries */ +typedef Elf64_Syminfo GElf_Syminfo; /* Symbol information */ + +#define GELF_M_INFO ELF64_M_INFO +#define GELF_M_SIZE ELF64_M_SIZE +#define GELF_M_SYM ELF64_M_SYM + +#define GELF_R_INFO ELF64_R_INFO +#define GELF_R_SYM ELF64_R_SYM +#define GELF_R_TYPE ELF64_R_TYPE +#define GELF_R_TYPE_DATA ELF64_R_TYPE_DATA +#define GELF_R_TYPE_ID ELF64_R_TYPE_ID +#define GELF_R_TYPE_INFO ELF64_R_TYPE_INFO + +#define GELF_ST_BIND ELF64_ST_BIND +#define GELF_ST_INFO ELF64_ST_INFO +#define GELF_ST_TYPE ELF64_ST_TYPE +#define GELF_ST_VISIBILITY ELF64_ST_VISIBILITY + +long gelf_checksum(Elf *_elf); +size_t gelf_fsize(Elf *_elf, Elf_Type _type, size_t _count, + unsigned int _version); +int gelf_getclass(Elf *_elf); +GElf_Dyn *gelf_getdyn(Elf_Data *_data, int _index, GElf_Dyn *_dst); +GElf_Ehdr *gelf_getehdr(Elf *_elf, GElf_Ehdr *_dst); +GElf_Phdr *gelf_getphdr(Elf *_elf, int _index, GElf_Phdr *_dst); +GElf_Rel *gelf_getrel(Elf_Data *_src, int _index, GElf_Rel *_dst); +GElf_Rela *gelf_getrela(Elf_Data *_src, int _index, GElf_Rela *_dst); +GElf_Shdr *gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst); +GElf_Sym *gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst); +GElf_Sym *gelf_getsymshndx(Elf_Data *_src, Elf_Data *_shindexsrc, + int _index, GElf_Sym *_dst, Elf32_Word *_shindexdst); +void * gelf_newehdr(Elf *_elf, int _class); +void * gelf_newphdr(Elf *_elf, size_t _phnum); +int gelf_update_dyn(Elf_Data *_dst, int _index, GElf_Dyn *_src); +int gelf_update_ehdr(Elf *_elf, GElf_Ehdr *_src); +int gelf_update_phdr(Elf *_elf, int _index, GElf_Phdr *_src); +int gelf_update_rel(Elf_Data *_dst, int _index, GElf_Rel *_src); +int gelf_update_rela(Elf_Data *_dst, int _index, GElf_Rela *_src); +int gelf_update_shdr(Elf_Scn *_dst, GElf_Shdr *_src); +int gelf_update_sym(Elf_Data *_dst, int _index, GElf_Sym *_src); +int gelf_update_symshndx(Elf_Data *_symdst, Elf_Data *_shindexdst, + int _index, GElf_Sym *_symsrc, Elf32_Word _shindexsrc); +Elf_Data *gelf_xlatetof(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode); +Elf_Data *gelf_xlatetom(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode); + +GElf_Cap *gelf_getcap(Elf_Data *_data, int _index, GElf_Cap *_cap); +GElf_Move *gelf_getmove(Elf_Data *_src, int _index, GElf_Move *_dst); +GElf_Syminfo *gelf_getsyminfo(Elf_Data *_src, int _index, GElf_Syminfo *_dst); +int gelf_update_cap(Elf_Data *_dst, int _index, GElf_Cap *_src); +int gelf_update_move(Elf_Data *_dst, int _index, GElf_Move *_src); +int gelf_update_syminfo(Elf_Data *_dst, int _index, GElf_Syminfo *_src); + +#ifdef __cplusplus +} +#endif + +#endif /* _GELF_H_ */ diff --git a/simulators/gem5/ext/libelf/gelf_checksum.c b/simulators/gem5/ext/libelf/gelf_checksum.c new file mode 100644 index 00000000..105cd288 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_checksum.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gelf.h" +#include "libelf.h" + +#include "_libelf.h" + +long +elf32_checksum(Elf *e) +{ + return (_libelf_checksum(e, ELFCLASS32)); +} + +long +elf64_checksum(Elf *e) +{ + return (_libelf_checksum(e, ELFCLASS64)); +} + +long +gelf_checksum(Elf *e) +{ + int ec; + if (e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0L); + } + return (_libelf_checksum(e, ec)); +} diff --git a/simulators/gem5/ext/libelf/gelf_dyn.c b/simulators/gem5/ext/libelf/gelf_dyn.c new file mode 100644 index 00000000..98206809 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_dyn.c @@ -0,0 +1,140 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "gelf.h" +#include "_libelf.h" + +GElf_Dyn * +gelf_getdyn(Elf_Data *d, int ndx, GElf_Dyn *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Dyn *dyn32; + Elf64_Dyn *dyn64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + dyn32 = (Elf32_Dyn *) d->d_buf + ndx; + + dst->d_tag = dyn32->d_tag; + dst->d_un.d_val = (Elf64_Xword) dyn32->d_un.d_val; + + } else { + + dyn64 = (Elf64_Dyn *) d->d_buf + ndx; + + *dst = *dyn64; + } + + return (dst); +} + +int +gelf_update_dyn(Elf_Data *d, int ndx, GElf_Dyn *ds) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Dyn *dyn32; + Elf64_Dyn *dyn64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || ds == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + dyn32 = (Elf32_Dyn *) d->d_buf + ndx; + + LIBELF_COPY_S32(dyn32, ds, d_tag); + LIBELF_COPY_U32(dyn32, ds, d_un.d_val); + } else { + dyn64 = (Elf64_Dyn *) d->d_buf + ndx; + + *dyn64 = *ds; + } + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_ehdr.c b/simulators/gem5/ext/libelf/gelf_ehdr.c new file mode 100644 index 00000000..c410f4a1 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_ehdr.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "gelf.h" +#include "libelf.h" +#include + +#include "_libelf.h" + +Elf32_Ehdr * +elf32_getehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS32, 0)); +} + +Elf64_Ehdr * +elf64_getehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS64, 0)); +} + +GElf_Ehdr * +gelf_getehdr(Elf *e, GElf_Ehdr *d) +{ + int ec; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + if (d == NULL || e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL) + return (NULL); + + (void) memcpy(d->e_ident, eh32->e_ident, sizeof(eh32->e_ident)); + d->e_type = eh32->e_type; + d->e_machine = eh32->e_machine; + d->e_version = eh32->e_version; + d->e_entry = eh32->e_entry; + d->e_phoff = eh32->e_phoff; + d->e_shoff = eh32->e_shoff; + d->e_flags = eh32->e_flags; + d->e_ehsize = eh32->e_ehsize; + d->e_phentsize = eh32->e_phentsize; + d->e_phnum = eh32->e_phnum; + d->e_shentsize = eh32->e_shentsize; + d->e_shnum = eh32->e_shnum; + d->e_shstrndx = eh32->e_shstrndx; + + return (d); + } + + assert(ec == ELFCLASS64); + + if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL) + return (NULL); + *d = *eh64; + + return (d); +} + +Elf32_Ehdr * +elf32_newehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS32, 1)); +} + +Elf64_Ehdr * +elf64_newehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS64, 1)); +} + +void * +gelf_newehdr(Elf *e, int ec) +{ + if (e != NULL && + (ec == ELFCLASS32 || ec == ELFCLASS64)) + return (_libelf_ehdr(e, ec, 1)); + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} + +int +gelf_update_ehdr(Elf *e, GElf_Ehdr *s) +{ + int ec; + void *ehdr; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + if (s== NULL || e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + if (ec == ELFCLASS64) { + eh64 = (Elf64_Ehdr *) ehdr; + *eh64 = *s; + return (1); + } + + eh32 = (Elf32_Ehdr *) ehdr; + + (void) memcpy(eh32->e_ident, s->e_ident, sizeof(eh32->e_ident)); + + eh32->e_type = s->e_type; + eh32->e_machine = s->e_machine; + eh32->e_version = s->e_version; + LIBELF_COPY_U32(eh32, s, e_entry); + LIBELF_COPY_U32(eh32, s, e_phoff); + LIBELF_COPY_U32(eh32, s, e_shoff); + eh32->e_flags = s->e_flags; + eh32->e_ehsize = s->e_ehsize; + eh32->e_phentsize = s->e_phentsize; + eh32->e_phnum = s->e_phnum; + eh32->e_shentsize = s->e_shentsize; + eh32->e_shnum = s->e_shnum; + eh32->e_shstrndx = s->e_shstrndx; + + (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_fsize.c b/simulators/gem5/ext/libelf/gelf_fsize.c new file mode 100644 index 00000000..06add073 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_fsize.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gelf.h" +#include "libelf.h" + +#include "_libelf.h" + +size_t +elf32_fsize(Elf_Type t, size_t c, unsigned int v) +{ + return (_libelf_fsize(t, ELFCLASS32, v, c)); +} + +size_t +elf64_fsize(Elf_Type t, size_t c, unsigned int v) +{ + return (_libelf_fsize(t, ELFCLASS64, v, c)); +} + +size_t +gelf_fsize(Elf *e, Elf_Type t, size_t c, unsigned int v) +{ + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_class == ELFCLASS32 || e->e_class == ELFCLASS64) + return (_libelf_fsize(t, e->e_class, v, c)); + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); +} diff --git a/simulators/gem5/ext/libelf/gelf_getclass.c b/simulators/gem5/ext/libelf/gelf_getclass.c new file mode 100644 index 00000000..96f2007a --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_getclass.c @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gelf.h" + +#include "_libelf.h" + +int +gelf_getclass(Elf *e) +{ + return (e != NULL ? e->e_class : ELFCLASSNONE); +} diff --git a/simulators/gem5/ext/libelf/gelf_phdr.c b/simulators/gem5/ext/libelf/gelf_phdr.c new file mode 100644 index 00000000..6125ec67 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_phdr.c @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "gelf.h" +#include "libelf.h" + +#include "_libelf.h" + +Elf32_Phdr * +elf32_getphdr(Elf *e) +{ + return (_libelf_getphdr(e, ELFCLASS32)); +} + +Elf64_Phdr * +elf64_getphdr(Elf *e) +{ + return (_libelf_getphdr(e, ELFCLASS64)); +} + +GElf_Phdr * +gelf_getphdr(Elf *e, int index, GElf_Phdr *d) +{ + int ec; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + Elf32_Phdr *ep32; + Elf64_Phdr *ep64; + + if (d == NULL || e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || + (e->e_kind != ELF_K_ELF) || index < 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL || + ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL)) + return (NULL); + + if (index >= eh32->e_phnum) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ep32 += index; + + d->p_type = ep32->p_type; + d->p_offset = ep32->p_offset; + d->p_vaddr = (Elf64_Addr) ep32->p_vaddr; + d->p_paddr = (Elf64_Addr) ep32->p_paddr; + d->p_filesz = (Elf64_Xword) ep32->p_filesz; + d->p_memsz = (Elf64_Xword) ep32->p_memsz; + d->p_flags = ep32->p_flags; + d->p_align = (Elf64_Xword) ep32->p_align; + + } else { + if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL || + (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL) + return (NULL); + + if (index >= eh64->e_phnum) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ep64 += index; + + *d = *ep64; + } + + return (d); +} + +Elf32_Phdr * +elf32_newphdr(Elf *e, size_t count) +{ + return (_libelf_newphdr(e, ELFCLASS32, count)); +} + +Elf64_Phdr * +elf64_newphdr(Elf *e, size_t count) +{ + return (_libelf_newphdr(e, ELFCLASS64, count)); +} + +void * +gelf_newphdr(Elf *e, size_t count) +{ + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + return (_libelf_newphdr(e, e->e_class, count)); +} + +int +gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s) +{ + int ec, phnum; + void *ehdr; + Elf32_Phdr *ph32; + Elf64_Phdr *ph64; + + if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + if (ec == ELFCLASS32) + phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; + else + phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; + + if (ndx < 0 || ndx > phnum) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS64) { + ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx; + *ph64 = *s; + return (1); + } + + ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx; + + ph32->p_type = s->p_type; + ph32->p_flags = s->p_flags; + LIBELF_COPY_U32(ph32, s, p_offset); + LIBELF_COPY_U32(ph32, s, p_vaddr); + LIBELF_COPY_U32(ph32, s, p_paddr); + LIBELF_COPY_U32(ph32, s, p_filesz); + LIBELF_COPY_U32(ph32, s, p_memsz); + LIBELF_COPY_U32(ph32, s, p_align); + + (void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_rel.c b/simulators/gem5/ext/libelf/gelf_rel.c new file mode 100644 index 00000000..56061380 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_rel.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "gelf.h" + +#include "_libelf.h" + +GElf_Rel * +gelf_getrel(Elf_Data *d, int ndx, GElf_Rel *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rel *rel32; + Elf64_Rel *rel64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_REL, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + rel32 = (Elf32_Rel *) d->d_buf + ndx; + + dst->r_offset = (Elf64_Addr) rel32->r_offset; + dst->r_info = (Elf64_Xword) rel32->r_info; + + } else { + + rel64 = (Elf64_Rel *) d->d_buf + ndx; + + *dst = *rel64; + } + + return (dst); +} + +int +gelf_update_rel(Elf_Data *d, int ndx, GElf_Rel *dr) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rel *rel32; + Elf64_Rel *rel64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dr == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_REL, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + rel32 = (Elf32_Rel *) d->d_buf + ndx; + + LIBELF_COPY_U32(rel32, dr, r_offset); + LIBELF_COPY_U32(rel32, dr, r_info); + } else { + rel64 = (Elf64_Rel *) d->d_buf + ndx; + + *rel64 = *dr; + } + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_rela.c b/simulators/gem5/ext/libelf/gelf_rela.c new file mode 100644 index 00000000..fbd2a2cc --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_rela.c @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "gelf.h" + +#include "_libelf.h" + +GElf_Rela * +gelf_getrela(Elf_Data *d, int ndx, GElf_Rela *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rela *rela32; + Elf64_Rela *rela64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + rela32 = (Elf32_Rela *) d->d_buf + ndx; + + dst->r_offset = (Elf64_Addr) rela32->r_offset; + dst->r_info = (Elf64_Xword) rela32->r_info; + dst->r_addend = (Elf64_Sxword) rela32->r_addend; + + } else { + + rela64 = (Elf64_Rela *) d->d_buf + ndx; + + *dst = *rela64; + } + + return (dst); +} + +int +gelf_update_rela(Elf_Data *d, int ndx, GElf_Rela *dr) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rela *rela32; + Elf64_Rela *rela64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dr == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + rela32 = (Elf32_Rela *) d->d_buf + ndx; + + LIBELF_COPY_U32(rela32, dr, r_offset); + LIBELF_COPY_U32(rela32, dr, r_info); + LIBELF_COPY_S32(rela32, dr, r_addend); + } else { + rela64 = (Elf64_Rela *) d->d_buf + ndx; + + *rela64 = *dr; + } + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_shdr.c b/simulators/gem5/ext/libelf/gelf_shdr.c new file mode 100644 index 00000000..16d6434f --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_shdr.c @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "gelf.h" +#include "libelf.h" + +#include "_libelf.h" + +Elf32_Shdr * +elf32_getshdr(Elf_Scn *s) +{ + return (_libelf_getshdr(s, ELFCLASS32)); +} + +Elf64_Shdr * +elf64_getshdr(Elf_Scn *s) +{ + return (_libelf_getshdr(s, ELFCLASS64)); +} + +GElf_Shdr * +gelf_getshdr(Elf_Scn *s, GElf_Shdr *d) +{ + int ec; + void *sh; + Elf32_Shdr *sh32; + Elf64_Shdr *sh64; + + if (d == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL) + return (NULL); + + ec = s->s_elf->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) { + sh32 = (Elf32_Shdr *) sh; + + d->sh_name = sh32->sh_name; + d->sh_type = sh32->sh_type; + d->sh_flags = (Elf64_Xword) sh32->sh_flags; + d->sh_addr = (Elf64_Addr) sh32->sh_addr; + d->sh_offset = (Elf64_Off) sh32->sh_offset; + d->sh_size = (Elf64_Xword) sh32->sh_size; + d->sh_link = sh32->sh_link; + d->sh_info = sh32->sh_info; + d->sh_addralign = (Elf64_Xword) sh32->sh_addralign; + d->sh_entsize = (Elf64_Xword) sh32->sh_entsize; + } else { + sh64 = (Elf64_Shdr *) sh; + *d = *sh64; + } + + return (d); +} + +int +gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *s) +{ + int ec; + Elf *e; + Elf32_Shdr *sh32; + + + if (s == NULL || scn == NULL || (e = scn->s_elf) == NULL || + e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if (ec == ELFCLASS64) { + scn->s_shdr.s_shdr64 = *s; + return (1); + } + + sh32 = &scn->s_shdr.s_shdr32; + + sh32->sh_name = s->sh_name; + sh32->sh_type = s->sh_type; + LIBELF_COPY_U32(sh32, s, sh_flags); + LIBELF_COPY_U32(sh32, s, sh_addr); + LIBELF_COPY_U32(sh32, s, sh_offset); + LIBELF_COPY_U32(sh32, s, sh_size); + sh32->sh_link = s->sh_link; + sh32->sh_info = s->sh_info; + LIBELF_COPY_U32(sh32, s, sh_addralign); + LIBELF_COPY_U32(sh32, s, sh_entsize); + + (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_sym.c b/simulators/gem5/ext/libelf/gelf_sym.c new file mode 100644 index 00000000..78c8a087 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_sym.c @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "gelf.h" + +#include "_libelf.h" + +GElf_Sym * +gelf_getsym(Elf_Data *d, int ndx, GElf_Sym *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Sym *sym32; + Elf64_Sym *sym64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + + sym32 = (Elf32_Sym *) d->d_buf + ndx; + + dst->st_name = sym32->st_name; + dst->st_value = (Elf64_Addr) sym32->st_value; + dst->st_size = (Elf64_Xword) sym32->st_size; + dst->st_info = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info), + ELF32_ST_TYPE(sym32->st_info)); + dst->st_other = sym32->st_other; + dst->st_shndx = sym32->st_shndx; + } else { + + sym64 = (Elf64_Sym *) d->d_buf + ndx; + + *dst = *sym64; + } + + return (dst); +} + +int +gelf_update_sym(Elf_Data *d, int ndx, GElf_Sym *gs) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Sym *sym32; + Elf64_Sym *sym64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || gs == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + sym32 = (Elf32_Sym *) d->d_buf + ndx; + + sym32->st_name = gs->st_name; + sym32->st_info = gs->st_info; + sym32->st_other = gs->st_other; + sym32->st_shndx = gs->st_shndx; + + LIBELF_COPY_U32(sym32, gs, st_value); + LIBELF_COPY_U32(sym32, gs, st_size); + } else { + sym64 = (Elf64_Sym *) d->d_buf + ndx; + + *sym64 = *gs; + } + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_symshndx.c b/simulators/gem5/ext/libelf/gelf_symshndx.c new file mode 100644 index 00000000..ec948fd7 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_symshndx.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "gelf.h" + +#include "_libelf.h" + +GElf_Sym * +gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst, + Elf32_Word *shindex) +{ + int ec; + Elf *e; + Elf_Scn *scn; + size_t msz; + uint32_t sh_type; + + if (gelf_getsym(d, ndx, dst) == 0) + return (NULL); + + if (id == NULL || (scn = id->d_scn) == NULL || + (e = scn->s_elf) == NULL || (e != d->d_scn->s_elf) || + shindex == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || + id->d_type != ELF_T_WORD) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= id->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + *shindex = ((Elf32_Word *) id->d_buf)[ndx]; + + return (dst); +} + +int +gelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs, + Elf32_Word xindex) +{ + int ec; + Elf *e; + Elf_Scn *scn; + size_t msz; + uint32_t sh_type; + + if (gelf_update_sym(d, ndx, gs) == 0) + return (0); + + if (id == NULL || (scn = id->d_scn) == NULL || + (e = scn->s_elf) == NULL || (e != d->d_scn->s_elf)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || + d->d_type != ELF_T_WORD) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= id->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + *(((Elf32_Word *) id->d_buf) + ndx) = xindex; + + return (1); +} diff --git a/simulators/gem5/ext/libelf/gelf_xlate.c b/simulators/gem5/ext/libelf/gelf_xlate.c new file mode 100644 index 00000000..8ab98ad5 --- /dev/null +++ b/simulators/gem5/ext/libelf/gelf_xlate.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gelf.h" +#include "libelf.h" +#include + +#include "_libelf.h" + + +Elf_Data * +elf32_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOFILE); +} + +Elf_Data * +elf64_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOFILE); +} + +Elf_Data * +elf32_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOMEMORY); +} + +Elf_Data * +elf64_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOMEMORY); +} + +Elf_Data * +gelf_xlatetom(Elf *e, Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + if (e != NULL) + return (_libelf_xlate(dst, src, encoding, e->e_class, + ELF_TOMEMORY)); + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} + +Elf_Data * +gelf_xlatetof(Elf *e, Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + if (e != NULL) + return (_libelf_xlate(dst, src, encoding, e->e_class, + ELF_TOFILE)); + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} diff --git a/simulators/gem5/ext/libelf/libelf.c b/simulators/gem5/ext/libelf/libelf.c new file mode 100644 index 00000000..73f25a21 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "libelf.h" +#include "_libelf.h" + +struct _libelf_globals * +_libelf_private() +{ + static int initialized = 0; + static struct _libelf_globals private; + + if (!initialized) { + uint32_t endian_test = ELFDATA2MSB << 24 | ELFDATA2LSB; + + private.libelf_arch = EM_NONE; + private.libelf_byteorder = *(char *)&endian_test; + private.libelf_class = ELFCLASSNONE; + private.libelf_error = 0; + private.libelf_fillchar = 0; + private.libelf_version = EV_NONE; + initialized = 1; + } + + return &private; +} diff --git a/simulators/gem5/ext/libelf/libelf.h b/simulators/gem5/ext/libelf/libelf.h new file mode 100644 index 00000000..51b9a851 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf.h @@ -0,0 +1,249 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/libelf.h,v 1.1 2006/11/11 17:16:33 jkoshy Exp $ + */ + +#ifndef _LIBELF_H_ +#define _LIBELF_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "elf_queue.h" +#include "elf32.h" +#include "elf64.h" + +/* Library private data structures */ +typedef struct _Elf Elf; +typedef struct _Elf_Scn Elf_Scn; + +/* File types */ +typedef enum { + ELF_K_NONE = 0, + ELF_K_AR, /* `ar' archives */ + ELF_K_COFF, /* COFF files (unsupported) */ + ELF_K_ELF, /* ELF files */ + ELF_K_NUM +} Elf_Kind; + +#define ELF_K_FIRST ELF_K_NONE +#define ELF_K_LAST ELF_K_NUM + +/* Data types */ +typedef enum { + ELF_T_ADDR, + ELF_T_BYTE, + ELF_T_CAP, + ELF_T_DYN, + ELF_T_EHDR, + ELF_T_HALF, + ELF_T_LWORD, + ELF_T_MOVE, + ELF_T_MOVEP, + ELF_T_NOTE, + ELF_T_OFF, + ELF_T_PHDR, + ELF_T_REL, + ELF_T_RELA, + ELF_T_SHDR, + ELF_T_SWORD, + ELF_T_SXWORD, + ELF_T_SYMINFO, + ELF_T_SYM, + ELF_T_VDEF, + ELF_T_VNEED, + ELF_T_WORD, + ELF_T_XWORD, + ELF_T_NUM +} Elf_Type; + +#define ELF_T_FIRST ELF_T_ADDR +#define ELF_T_LAST ELF_T_XWORD + +/* Commands */ +typedef enum { + ELF_C_NULL = 0, + ELF_C_CLR, + ELF_C_FDDONE, + ELF_C_FDREAD, + ELF_C_RDWR, + ELF_C_READ, + ELF_C_SET, + ELF_C_WRITE, + ELF_C_NUM +} Elf_Cmd; + +#define ELF_C_FIRST ELF_C_NULL +#define ELF_C_LAST ELF_C_NUM + +/* + * An `Elf_Data' structure describes data in an + * ELF section. + */ +typedef struct _Elf_Data { + /* + * `Public' members that are part of the ELF(3) API. + */ + uint64_t d_align; + void *d_buf; + uint64_t d_off; + uint64_t d_size; + Elf_Type d_type; + unsigned int d_version; + + /* + * Members that are not part of the public API. + */ + Elf_Scn *d_scn; /* containing section */ + unsigned int d_flags; + STAILQ_ENTRY(_Elf_Data) d_next; +} Elf_Data; + +/* + * An `Elf_Arhdr' structure describes an archive + * header. + */ +typedef struct { + time_t ar_date; + char *ar_name; /* archive member name */ + gid_t ar_gid; + mode_t ar_mode; + char *ar_rawname; /* 'raw' member name */ + size_t ar_size; + uid_t ar_uid; +} Elf_Arhdr; + +/* + * An `Elf_Arsym' describes an entry in the archive + * symbol table. + */ +typedef struct { + off_t as_off; /* byte offset to member's header */ + unsigned long as_hash; /* elf_hash() value for name */ + char *as_name; /* null terminated symbol name */ +} Elf_Arsym; + +/* + * Error numbers. + */ + +enum Elf_Error { + ELF_E_NONE, /* No error */ + ELF_E_ARCHIVE, /* Malformed ar(1) archive */ + ELF_E_ARGUMENT, /* Invalid argument */ + ELF_E_CLASS, /* Mismatched ELF class */ + ELF_E_DATA, /* Invalid data descriptor */ + ELF_E_HEADER, /* Missing or malformed ELF header */ + ELF_E_IO, /* I/O error */ + ELF_E_LAYOUT, /* Layout constraint violation */ + ELF_E_MODE, /* Wrong mode for ELF descriptor */ + ELF_E_RANGE, /* Value out of range */ + ELF_E_RESOURCE, /* Resource exhaustion */ + ELF_E_SECTION, /* Invalid section descriptor */ + ELF_E_SEQUENCE, /* API calls out of sequence */ + ELF_E_UNIMPL, /* Feature is unimplemented */ + ELF_E_VERSION, /* Unknown API version */ + ELF_E_NUM /* Max error number */ +}; + +/* + * Flags defined by the API. + */ + +#define ELF_F_LAYOUT 0x001U /* application will layout the file */ +#define ELF_F_DIRTY 0x002U /* a section or ELF file is dirty */ + +Elf *elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf); +int elf_cntl(Elf *_elf, Elf_Cmd _cmd); +int elf_end(Elf *_elf); +const char *elf_errmsg(int _error); +int elf_errno(void); +void elf_fill(int _fill); +unsigned int elf_flagdata(Elf_Data *_data, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagehdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagelf(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagphdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagscn(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagshdr(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags); +Elf_Arhdr *elf_getarhdr(Elf *_elf); +Elf_Arsym *elf_getarsym(Elf *_elf, size_t *_ptr); +off_t elf_getbase(Elf *_elf); +Elf_Data *elf_getdata(Elf_Scn *, Elf_Data *); +char *elf_getident(Elf *_elf, size_t *_ptr); +int elf_getphnum(Elf *_elf, size_t *_dst); +Elf_Scn *elf_getscn(Elf *_elf, size_t _index); +int elf_getshnum(Elf *_elf, size_t *_dst); +int elf_getshstrndx(Elf *_elf, size_t *_dst); +unsigned long elf_hash(const char *_name); +Elf_Kind elf_kind(Elf *_elf); +Elf *elf_memory(char *_image, size_t _size); +size_t elf_ndxscn(Elf_Scn *_scn); +Elf_Data *elf_newdata(Elf_Scn *_scn); +Elf_Scn *elf_newscn(Elf *_elf); +Elf_Scn *elf_nextscn(Elf *_elf, Elf_Scn *_scn); +Elf_Cmd elf_next(Elf *_elf); +off_t elf_rand(Elf *_elf, off_t _off); +Elf_Data *elf_rawdata(Elf_Scn *_scn, Elf_Data *_data); +char *elf_rawfile(Elf *_elf, size_t *_size); +int elf_setshstrndx(Elf *_elf, size_t _shnum); +char *elf_strptr(Elf *_elf, size_t _section, size_t _offset); +off_t elf_update(Elf *_elf, Elf_Cmd _cmd); +unsigned int elf_version(unsigned int _version); + +long elf32_checksum(Elf *_elf); +size_t elf32_fsize(Elf_Type _type, size_t _count, + unsigned int _version); +Elf32_Ehdr *elf32_getehdr(Elf *_elf); +Elf32_Phdr *elf32_getphdr(Elf *_elf); +Elf32_Shdr *elf32_getshdr(Elf_Scn *_scn); +Elf32_Ehdr *elf32_newehdr(Elf *_elf); +Elf32_Phdr *elf32_newphdr(Elf *_elf, size_t _count); +Elf_Data *elf32_xlatetof(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); +Elf_Data *elf32_xlatetom(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); + +long elf64_checksum(Elf *_elf); +size_t elf64_fsize(Elf_Type _type, size_t _count, + unsigned int _version); +Elf64_Ehdr *elf64_getehdr(Elf *_elf); +Elf64_Phdr *elf64_getphdr(Elf *_elf); +Elf64_Shdr *elf64_getshdr(Elf_Scn *_scn); +Elf64_Ehdr *elf64_newehdr(Elf *_elf); +Elf64_Phdr *elf64_newphdr(Elf *_elf, size_t _count); +Elf_Data *elf64_xlatetof(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); +Elf_Data *elf64_xlatetom(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBELF_H_ */ diff --git a/simulators/gem5/ext/libelf/libelf_align.c b/simulators/gem5/ext/libelf/libelf_align.c new file mode 100644 index 00000000..af44ecdb --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_align.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +//#include +//#include + +#include "libelf.h" + +#include "_libelf.h" + +struct align { + int a32; + int a64; +}; + +#ifdef __GNUC__ +#define MALIGN(N) { \ + .a32 = __alignof__(Elf32_##N), \ + .a64 = __alignof__(Elf64_##N) \ + } +#define MALIGN64(V) { \ + .a32 = 0, \ + .a64 = __alignof__(Elf64_##V) \ + } +#else +#error Need the __alignof__ builtin. +#endif +#define UNSUPPORTED() { \ + .a32 = 0, \ + .a64 = 0 \ + } + +static struct align malign[ELF_T_NUM] = { + [ELF_T_ADDR] = MALIGN(Addr), + [ELF_T_BYTE] = { .a32 = 1, .a64 = 1 }, + [ELF_T_CAP] = MALIGN(Cap), + [ELF_T_DYN] = MALIGN(Dyn), + [ELF_T_EHDR] = MALIGN(Ehdr), + [ELF_T_HALF] = MALIGN(Half), + [ELF_T_LWORD] = MALIGN(Lword), + [ELF_T_MOVE] = MALIGN(Move), + [ELF_T_MOVEP] = UNSUPPORTED(), + [ELF_T_NOTE] = MALIGN(Nhdr), + [ELF_T_OFF] = MALIGN(Off), + [ELF_T_PHDR] = MALIGN(Phdr), + [ELF_T_REL] = MALIGN(Rel), + [ELF_T_RELA] = MALIGN(Rela), + [ELF_T_SHDR] = MALIGN(Shdr), + [ELF_T_SWORD] = MALIGN(Sword), + [ELF_T_SXWORD] = MALIGN64(Sxword), + [ELF_T_SYM] = MALIGN(Sym), + [ELF_T_SYMINFO] = MALIGN(Syminfo), + [ELF_T_VDEF] = MALIGN(Verdef), + [ELF_T_VNEED] = MALIGN(Verneed), + [ELF_T_WORD] = MALIGN(Word), + [ELF_T_XWORD] = MALIGN64(Xword) +}; + +int +_libelf_malign(Elf_Type t, int elfclass) +{ + if (t >= ELF_T_NUM || (int) t < 0) + return (0); + + return (elfclass == ELFCLASS32 ? malign[t].a32 : + malign[t].a64); +} + +#define FALIGN(A32,A64) { .a32 = (A32), .a64 = (A64) } + +static struct align falign[ELF_T_NUM] = { + [ELF_T_ADDR] = FALIGN(4,8), + [ELF_T_BYTE] = FALIGN(1,1), + [ELF_T_CAP] = FALIGN(4,8), + [ELF_T_DYN] = FALIGN(4,8), + [ELF_T_EHDR] = FALIGN(4,8), + [ELF_T_HALF] = FALIGN(2,2), + [ELF_T_LWORD] = FALIGN(8,8), + [ELF_T_MOVE] = FALIGN(8,8), + [ELF_T_MOVEP] = UNSUPPORTED(), + [ELF_T_NOTE] = FALIGN(4,4), + [ELF_T_OFF] = FALIGN(4,8), + [ELF_T_PHDR] = FALIGN(4,8), + [ELF_T_REL] = FALIGN(4,8), + [ELF_T_RELA] = FALIGN(4,8), + [ELF_T_SHDR] = FALIGN(4,8), + [ELF_T_SWORD] = FALIGN(4,4), + [ELF_T_SXWORD] = FALIGN(0,8), + [ELF_T_SYM] = FALIGN(4,8), + [ELF_T_SYMINFO] = FALIGN(2,2), + [ELF_T_VDEF] = FALIGN(4,4), + [ELF_T_VNEED] = FALIGN(4,4), + [ELF_T_WORD] = FALIGN(4,4), + [ELF_T_XWORD] = FALIGN(0,8) +}; + +int +_libelf_falign(Elf_Type t, int elfclass) +{ + if (t >= ELF_T_NUM || (int) t < 0) + return (0); + + return (elfclass == ELFCLASS32 ? falign[t].a32 : + falign[t].a64); +} diff --git a/simulators/gem5/ext/libelf/libelf_allocate.c b/simulators/gem5/ext/libelf/libelf_allocate.c new file mode 100644 index 00000000..9e1280c4 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_allocate.c @@ -0,0 +1,206 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Internal APIs + */ + +#include + +#include +#include "libelf.h" +#include +#include + +#include "_libelf.h" + +Elf * +_libelf_allocate_elf(void) +{ + Elf *e; + + if ((e = malloc(sizeof(*e))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return NULL; + } + + e->e_activations = 1; + e->e_arhdr = NULL; + e->e_byteorder = ELFDATANONE; + e->e_class = ELFCLASSNONE; + e->e_cmd = ELF_C_NULL; + e->e_fd = -1; + e->e_flags = 0; + e->e_kind = ELF_K_NONE; + e->e_parent = NULL; + e->e_rawfile = NULL; + e->e_rawsize = 0; + e->e_version = LIBELF_PRIVATE(version); + + (void) memset(&e->e_u, 0, sizeof(e->e_u)); + + return (e); +} + +void +_libelf_init_elf(Elf *e, Elf_Kind kind) +{ + assert(e != NULL); + assert(e->e_kind == ELF_K_NONE); + + e->e_kind = kind; + + switch (kind) { + case ELF_K_ELF: + STAILQ_INIT(&e->e_u.e_elf.e_scn); + break; + default: + break; + } +} + +#define FREE(P) do { \ + if (P) \ + free(P); \ + } while (0) + + +Elf * +_libelf_release_elf(Elf *e) +{ + switch (e->e_kind) { + case ELF_K_AR: + FREE(e->e_u.e_ar.e_symtab); + break; + + case ELF_K_ELF: + switch (e->e_class) { + case ELFCLASS32: + FREE(e->e_u.e_elf.e_ehdr.e_ehdr32); + FREE(e->e_u.e_elf.e_phdr.e_phdr32); + break; + case ELFCLASS64: + FREE(e->e_u.e_elf.e_ehdr.e_ehdr64); + FREE(e->e_u.e_elf.e_phdr.e_phdr64); + break; + } + + assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); + + if (e->e_arhdr) { + FREE(e->e_arhdr->ar_name); + FREE(e->e_arhdr->ar_rawname); + free(e->e_arhdr); + } + + break; + + default: + break; + } + + free(e); + + return (NULL); +} + +Elf_Data * +_libelf_allocate_data(Elf_Scn *s) +{ + Elf_Data *d; + + if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + d->d_scn = s; + + return (d); +} + +Elf_Data * +_libelf_release_data(Elf_Data *d) +{ + + if (d->d_flags & LIBELF_F_MALLOCED) + free(d->d_buf); + + free(d); + + return (NULL); +} + +Elf_Scn * +_libelf_allocate_scn(Elf *e, size_t ndx) +{ + Elf_Scn *s; + + if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return (NULL); + } + + s->s_elf = e; + s->s_ndx = ndx; + + STAILQ_INIT(&s->s_data); + STAILQ_INIT(&s->s_rawdata); + + STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next); + + return (s); +} + +Elf_Scn * +_libelf_release_scn(Elf_Scn *s) +{ + Elf *e; + Elf_Data *d, *td; + + assert(s != NULL); + + STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { + STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next); + d = _libelf_release_data(d); + } + + STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) { + assert((d->d_flags & LIBELF_F_MALLOCED) == 0); + STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next); + d = _libelf_release_data(d); + } + + e = s->s_elf; + + assert(e != NULL); + + STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); + + free(s); + + return (NULL); +} diff --git a/simulators/gem5/ext/libelf/libelf_ar.c b/simulators/gem5/ext/libelf/libelf_ar.c new file mode 100644 index 00000000..01e16245 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_ar.c @@ -0,0 +1,481 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "libelf.h" +#include +#include + +#include "_libelf.h" + +#define LIBELF_NALLOC_SIZE 16 + +/* + * `ar' archive handling. + * + * `ar' archives start with signature `ARMAG'. Each archive member is + * preceded by a header containing meta-data for the member. This + * header is described in (struct ar_hdr). The header always + * starts on an even address. File data is padded with "\n" + * characters to keep this invariant. + * + * Special considerations for `ar' archives: + * + * The `ar' header only has space for a 16 character file name. File + * names are terminated with a '/', so this effectively leaves 15 + * characters for the actual file name. In order to accomodate longer + * file names, names may be stored in a separate 'string table' and + * referenced indirectly by a member header. The string table itself + * appears as an archive member with name "// ". An indirect file name + * in an `ar' header matches the pattern "/[0-9]*". The digits form a + * decimal number that corresponds to a byte offset into the string + * table where the actual file name of the object starts. Strings in + * the string table are padded to start on even addresses. + * + * Archives may also have a symbol table (see ranlib(1)), mapping + * program symbols to object files inside the archive. A symbol table + * uses a file name of "/ " in its archive header. The symbol table + * is structured as: + * - a 4-byte count of entries stored as a binary value, MSB first + * - 'n' 4-byte offsets, stored as binary values, MSB first + * - 'n' NUL-terminated strings, for ELF symbol names, stored unpadded. + * + * If the symbol table and string table are is present in an archive + * they must be the very first objects and in that order. + */ + +/* + * Convert a string bounded by `start' and `start+sz' (exclusive) to a + * number in the specified base. + */ +static int +_libelf_ar_get_number(char *s, size_t sz, int base, size_t *ret) +{ + int c, v; + size_t r; + char *e; + + assert(base <= 10); + + e = s + sz; + + /* skip leading blanks */ + for (;s < e && (c = *s) == ' '; s++) + ; + + r = 0L; + for (;s < e; s++) { + if ((c = *s) == ' ') + break; + if (c < '0' || c > '9') + return (0); + v = c - '0'; + if (v >= base) /* Illegal digit. */ + break; + r *= base; + r += v; + } + + *ret = r; + + return (1); +} + +/* + * Retrieve a string from a name field. If `rawname' is set, leave + * ar(1) control characters in. + */ +static char * +_libelf_ar_get_string(const char *buf, size_t bufsize, int rawname) +{ + const char *q; + char *r; + size_t sz; + + if (rawname) + sz = bufsize + 1; + else { + /* Skip back over trailing blanks. */ + for (q = buf + bufsize - 1; q >= buf && *q == ' '; --q) + ; + + if (q < buf) { + /* + * If the input buffer only had blanks in it, + * return a zero-length string. + */ + buf = ""; + sz = 1; + } else { + /* + * Remove the trailing '/' character, but only + * if the name isn't one of the special names + * "/" and "//". + */ + if (q > buf + 1 || + (q == (buf + 1) && *buf != '/')) + q--; + + sz = q - buf + 2; /* Space for a trailing NUL. */ + } + } + + if ((r = malloc(sz)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + (void) strncpy(r, buf, sz); + r[sz - 1] = '\0'; + + return (r); +} + +/* + * Retrieve the full name of the archive member. + */ +static char * +_libelf_ar_get_name(char *buf, size_t bufsize, Elf *e) +{ + char c, *q, *r, *s; + size_t len; + size_t offset; + + assert(e->e_kind == ELF_K_AR); + + if (buf[0] == '/' && (c = buf[1]) >= '0' && c <= '9') { + /* + * The value in field ar_name is a decimal offset into + * the archive string table where the actual name + * resides. + */ + if (_libelf_ar_get_number(buf + 1, bufsize - 1, 10, + &offset) == 0) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + if (offset > e->e_u.e_ar.e_rawstrtabsz) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + s = q = e->e_u.e_ar.e_rawstrtab + offset; + r = e->e_u.e_ar.e_rawstrtab + e->e_u.e_ar.e_rawstrtabsz; + + for (s = q; s < r && *s != '/'; s++) + ; + len = s - q + 1; /* space for the trailing NUL */ + + if ((s = malloc(len)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + (void) strncpy(s, q, len); + s[len - 1] = '\0'; + + return (s); + } + + /* + * Normal 'name' + */ + return (_libelf_ar_get_string(buf, bufsize, 0)); +} + + +Elf_Arhdr * +_libelf_ar_gethdr(Elf *e) +{ + Elf *parent; + struct ar_hdr *arh; + Elf_Arhdr *eh; + size_t n; + + if ((parent = e->e_parent) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + arh = (struct ar_hdr *) ((uintptr_t) e->e_rawfile - sizeof(struct ar_hdr)); + + assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG); + assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile + parent->e_rawsize - + sizeof(struct ar_hdr)); + + if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + e->e_arhdr = eh; + eh->ar_name = eh->ar_rawname = NULL; + + if ((eh->ar_name = _libelf_ar_get_name(arh->ar_name, sizeof(arh->ar_name), + parent)) == NULL) + goto error; + + if (_libelf_ar_get_number(arh->ar_uid, sizeof(arh->ar_uid), 10, &n) == 0) + goto error; + eh->ar_uid = (uid_t) n; + + if (_libelf_ar_get_number(arh->ar_gid, sizeof(arh->ar_gid), 10, &n) == 0) + goto error; + eh->ar_gid = (gid_t) n; + + if (_libelf_ar_get_number(arh->ar_mode, sizeof(arh->ar_mode), 8, &n) == 0) + goto error; + eh->ar_mode = (mode_t) n; + + if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &n) == 0) + goto error; + eh->ar_size = n; + + if ((eh->ar_rawname = _libelf_ar_get_string(arh->ar_name, + sizeof(arh->ar_name), 1)) == NULL) + goto error; + + return (eh); + + error: + if (eh) { + if (eh->ar_name) + free(eh->ar_name); + if (eh->ar_rawname) + free(eh->ar_rawname); + free(eh); + } + e->e_arhdr = NULL; + + return (NULL); +} + +Elf * +_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf) +{ + Elf *e; + off_t next; + struct ar_hdr *arh; + size_t sz; + + assert(elf->e_kind == ELF_K_AR); + + next = elf->e_u.e_ar.e_next; + + /* + * `next' is only set to zero by elf_next() when the last + * member of an archive is processed. + */ + if (next == (off_t) 0) + return (NULL); + + assert((next & 1) == 0); + + arh = (struct ar_hdr *) (elf->e_rawfile + next); + + if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &sz) == 0) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + assert(sz > 0); + + arh++; /* skip over archive member header */ + + if ((e = elf_memory((char *) arh, sz)) == NULL) + return (NULL); + + e->e_fd = fd; + e->e_cmd = c; + + elf->e_u.e_ar.e_nchildren++; + e->e_parent = elf; + + return (e); +} + +Elf * +_libelf_ar_open(Elf *e) +{ + int i; + char *s, *end; + size_t sz; + struct ar_hdr arh; + + e->e_kind = ELF_K_AR; + e->e_u.e_ar.e_nchildren = 0; + e->e_u.e_ar.e_next = (off_t) -1; + + /* + * Look for special members. + */ + + s = e->e_rawfile + SARMAG; + end = e->e_rawfile + e->e_rawsize; + + assert(e->e_rawsize > 0); + + /* + * Look for magic names "/ " and "// " in the first two entries + * of the archive. + */ + for (i = 0; i < 2; i++) { + + if (s + sizeof(arh) > end) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + (void) memcpy(&arh, s, sizeof(arh)); + + if (arh.ar_fmag[0] != '`' || arh.ar_fmag[1] != '\n') { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + if (arh.ar_name[0] != '/') /* not a special symbol */ + break; + + if (_libelf_ar_get_number(arh.ar_size, sizeof(arh.ar_size), 10, &sz) == 0) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + assert(sz > 0); + + s += sizeof(arh); + + if (arh.ar_name[1] == ' ') { /* "/ " => symbol table */ + + e->e_u.e_ar.e_rawsymtab = s; + e->e_u.e_ar.e_rawsymtabsz = sz; + + } else if (arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') { + + /* "// " => string table for long file names */ + e->e_u.e_ar.e_rawstrtab = s; + e->e_u.e_ar.e_rawstrtabsz = sz; + } + + sz = LIBELF_ADJUST_AR_SIZE(sz); + + s += sz; + } + + e->e_u.e_ar.e_next = (off_t) (s - e->e_rawfile); + + return (e); +} + +/* + * An ar(1) symbol table has the following layout: + * + * The first 4 bytes are a binary count of the number of entries in the + * symbol table, stored MSB-first. + * + * Then there are 'n' 4-byte binary offsets, also stored MSB first. + * + * Following this, there are 'n' null-terminated strings. + */ + +#define GET_WORD(P, V) do { \ + (V) = 0; \ + (V) = (P)[0]; (V) <<= 8; \ + (V) += (P)[1]; (V) <<= 8; \ + (V) += (P)[2]; (V) <<= 8; \ + (V) += (P)[3]; \ + } while (0) + +#define INTSZ 4 + +Elf_Arsym * +_libelf_ar_process_symtab(Elf *e, size_t *count) +{ + size_t n, nentries, off; + Elf_Arsym *symtab, *sym; + char *p, *s, *end; + + assert(e != NULL); + assert(count != NULL); + + if (e->e_u.e_ar.e_rawsymtabsz < INTSZ) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + p = e->e_u.e_ar.e_rawsymtab; + end = p + e->e_u.e_ar.e_rawsymtabsz; + + GET_WORD(p, nentries); + p += INTSZ; + + if (nentries == 0 || p + nentries * INTSZ >= end) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + /* Allocate space for a nentries + a sentinel. */ + if ((symtab = malloc(sizeof(Elf_Arsym) * (nentries+1))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + s = p + (nentries * INTSZ); /* start of the string table. */ + + for (n = nentries, sym = symtab; n > 0; n--) { + off = 0; + + GET_WORD(p, off); + + sym->as_off = off; + sym->as_hash = elf_hash(s); + sym->as_name = s; + + p += INTSZ; + sym++; + + for (; s < end && *s++ != '\0';) /* skip to next string */ + ; + if (s > end) { + LIBELF_SET_ERROR(ARCHIVE, 0); + free(symtab); + return (NULL); + } + } + + /* Fill up the sentinel entry. */ + sym->as_name = NULL; + sym->as_hash = ~0UL; + sym->as_off = (off_t) 0; + + *count = e->e_u.e_ar.e_symtabsz = nentries + 1; + e->e_u.e_ar.e_symtab = symtab; + + return (symtab); +} diff --git a/simulators/gem5/ext/libelf/libelf_checksum.c b/simulators/gem5/ext/libelf/libelf_checksum.c new file mode 100644 index 00000000..14351759 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_checksum.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gelf.h" + +#include "_libelf.h" + +static unsigned long +_libelf_sum(unsigned long c, const unsigned char *s, size_t size) +{ + if (s == NULL || size == 0) + return (c); + + while (size--) + c += *s++; + + return (c); +} + +unsigned long +_libelf_checksum(Elf *e, int elfclass) +{ + size_t shn; + Elf_Scn *scn; + Elf_Data *d; + unsigned long checksum; + GElf_Ehdr eh; + GElf_Shdr shdr; + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0L); + } + + if (e->e_class != elfclass) { + LIBELF_SET_ERROR(CLASS, 0); + return (0L); + } + + if (gelf_getehdr(e, &eh) == NULL) + return (0); + + /* + * Iterate over all sections in the ELF file, computing the + * checksum along the way. + * + * The first section is always SHN_UNDEF and can be skipped. + * Non-allocatable sections are skipped, as are sections that + * could be affected by utilities such as strip(1). + */ + + checksum = 0; + for (shn = 1; shn < e->e_u.e_elf.e_nscn; shn++) { + if ((scn = elf_getscn(e, shn)) == NULL) + return (0); + if (gelf_getshdr(scn, &shdr) == NULL) + return (0); + if ((shdr.sh_flags & SHF_ALLOC) == 0 || + shdr.sh_type == SHT_DYNAMIC || + shdr.sh_type == SHT_DYNSYM) + continue; + + d = NULL; + while ((d = elf_rawdata(scn, d)) != NULL) + checksum = _libelf_sum(checksum, + (unsigned char *) d->d_buf, d->d_size); + } + + /* + * Return a 16-bit checksum compatible with Solaris. + */ + return (((checksum >> 16) & 0xFFFFUL) + (checksum & 0xFFFFUL)); +} diff --git a/simulators/gem5/ext/libelf/libelf_convert.m4 b/simulators/gem5/ext/libelf/libelf_convert.m4 new file mode 100644 index 00000000..1f21dbe4 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_convert.m4 @@ -0,0 +1,657 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include + +#include "elf32.h" +#include "elf64.h" +#include "libelf.h" +#include "_libelf.h" + +/* WARNING: GENERATED FROM __file__. */ + +/* + * Macros to swap various integral quantities. + */ + +#define SWAP_HALF(X) do { \ + uint16_t _x = (uint16_t) (X); \ + uint16_t _t = _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + (X) = _t; \ + } while (0) +#define SWAP_WORD(X) do { \ + uint32_t _x = (uint32_t) (X); \ + uint32_t _t = _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + (X) = _t; \ + } while (0) +#define SWAP_ADDR32(X) SWAP_WORD(X) +#define SWAP_OFF32(X) SWAP_WORD(X) +#define SWAP_SWORD(X) SWAP_WORD(X) +#define SWAP_WORD64(X) do { \ + uint64_t _x = (uint64_t) (X); \ + uint64_t _t = _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + (X) = _t; \ + } while (0) +#define SWAP_ADDR64(X) SWAP_WORD64(X) +#define SWAP_LWORD(X) SWAP_WORD64(X) +#define SWAP_OFF64(X) SWAP_WORD64(X) +#define SWAP_SXWORD(X) SWAP_WORD64(X) +#define SWAP_XWORD(X) SWAP_WORD64(X) + +/* + * Write out various integral values. The destination pointer could + * be unaligned. Values are written out in native byte order. The + * destination pointer is incremented after the write. + */ +#define WRITE_BYTE(P,X) do { \ + unsigned char *const _p = (unsigned char *) (P); \ + _p[0] = (unsigned char) (X); \ + (P) = _p + 1; \ + } while (0) +#define WRITE_HALF(P,X) do { \ + uint16_t _t = (X); \ + unsigned char *const _p = (unsigned char *) (P); \ + unsigned const char *const _q = (unsigned char *) &_t; \ + _p[0] = _q[0]; \ + _p[1] = _q[1]; \ + (P) = _p + 2; \ + } while (0) +#define WRITE_WORD(P,X) do { \ + uint32_t _t = (X); \ + unsigned char *const _p = (unsigned char *) (P); \ + unsigned const char *const _q = (unsigned char *) &_t; \ + _p[0] = _q[0]; \ + _p[1] = _q[1]; \ + _p[2] = _q[2]; \ + _p[3] = _q[3]; \ + (P) = _p + 4; \ + } while (0) +#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) +#define WRITE_OFF32(P,X) WRITE_WORD(P,X) +#define WRITE_SWORD(P,X) WRITE_WORD(P,X) +#define WRITE_WORD64(P,X) do { \ + uint64_t _t = (X); \ + unsigned char *const _p = (unsigned char *) (P); \ + unsigned const char *const _q = (unsigned char *) &_t; \ + _p[0] = _q[0]; \ + _p[1] = _q[1]; \ + _p[2] = _q[2]; \ + _p[3] = _q[3]; \ + _p[4] = _q[4]; \ + _p[5] = _q[5]; \ + _p[6] = _q[6]; \ + _p[7] = _q[7]; \ + (P) = _p + 8; \ + } while (0) +#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) +#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) +#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) +#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) +#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) +#define WRITE_IDENT(P,X) do { \ + (void) memcpy((P), (X), sizeof((X))); \ + (P) = (P) + EI_NIDENT; \ + } while (0) + +/* + * Read in various integral values. The source pointer could be + * unaligned. Values are read in in native byte order. The source + * pointer is incremented appropriately. + */ + +#define READ_BYTE(P,X) do { \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + (X) = _p[0]; \ + (P) = (P) + 1; \ + } while (0) +#define READ_HALF(P,X) do { \ + uint16_t _t; \ + unsigned char *const _q = (unsigned char *) &_t; \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + _q[0] = _p[0]; \ + _q[1] = _p[1]; \ + (P) = (P) + 2; \ + (X) = _t; \ + } while (0) +#define READ_WORD(P,X) do { \ + uint32_t _t; \ + unsigned char *const _q = (unsigned char *) &_t; \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + _q[0] = _p[0]; \ + _q[1] = _p[1]; \ + _q[2] = _p[2]; \ + _q[3] = _p[3]; \ + (P) = (P) + 4; \ + (X) = _t; \ + } while (0) +#define READ_ADDR32(P,X) READ_WORD(P,X) +#define READ_OFF32(P,X) READ_WORD(P,X) +#define READ_SWORD(P,X) READ_WORD(P,X) +#define READ_WORD64(P,X) do { \ + uint64_t _t; \ + unsigned char *const _q = (unsigned char *) &_t; \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + _q[0] = _p[0]; \ + _q[1] = _p[1]; \ + _q[2] = _p[2]; \ + _q[3] = _p[3]; \ + _q[4] = _p[4]; \ + _q[5] = _p[5]; \ + _q[6] = _p[6]; \ + _q[7] = _p[7]; \ + (P) = (P) + 8; \ + (X) = _t; \ + } while (0) +#define READ_ADDR64(P,X) READ_WORD64(P,X) +#define READ_LWORD(P,X) READ_WORD64(P,X) +#define READ_OFF64(P,X) READ_WORD64(P,X) +#define READ_SXWORD(P,X) READ_WORD64(P,X) +#define READ_XWORD(P,X) READ_WORD64(P,X) +#define READ_IDENT(P,X) do { \ + (void) memcpy((X), (P), sizeof((X))); \ + (P) = (P) + EI_NIDENT; \ + } while (0) + +#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) + +divert(-1) + +/* + * Generate conversion routines for converting between in-memory and + * file representations of Elf data structures. + * + * `In-memory' representations of an Elf data structure use natural + * alignments and native byte ordering. This allows arithmetic and + * casting to work as expected. On the other hand the `file' + * representation of an ELF data structure could be packed tighter + * than its `in-memory' representation, and could be of a differing + * byte order. An additional complication is that `ar' only pads data + * to even addresses and so ELF archive member data being read from + * inside an `ar' archive could end up at misaligned memory addresses. + * + * Consequently, casting the `char *' pointers that point to memory + * representations (i.e., source pointers for the *_tof() functions + * and the destination pointers for the *_tom() functions), is safe, + * as these pointers should be correctly aligned for the memory type + * already. However, pointers to file representations have to be + * treated as being potentially unaligned and no casting can be done. + */ + +include(SRCDIR`/elf_types.m4') + +/* + * `IGNORE'_* flags turn off generation of template code. + */ + +define(`IGNORE', + `define(IGNORE_$1`'32, 1) + define(IGNORE_$1`'64, 1)') + +IGNORE(MOVEP) +IGNORE(NOTE) + +define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ +define(IGNORE_NOTE, 1) +define(IGNORE_SXWORD32, 1) +define(IGNORE_XWORD32, 1) + +/* + * `BASE'_XXX flags cause class agnostic template functions + * to be generated. + */ + +define(`BASE_BYTE', 1) +define(`BASE_HALF', 1) +define(`BASE_NOTE', 1) +define(`BASE_WORD', 1) +define(`BASE_LWORD', 1) +define(`BASE_SWORD', 1) +define(`BASE_XWORD', 1) +define(`BASE_SXWORD', 1) + +/* + * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated + * for each primitive type. + */ + +define(`SIZEDEP_ADDR', 1) +define(`SIZEDEP_OFF', 1) + +/* + * `Primitive' ELF types are those that are an alias for an integral + * type. They have no internal structure. These can be copied using + * a `memcpy()', and byteswapped in straightforward way. + * + * Macro use: + * `$1': Name of the ELF type. + * `$2': C structure name suffix + * `$3': ELF class specifier for symbols, one of [`', `32', `64'] + * `$4': ELF class specifier for types, one of [`32', `64'] + */ +define(`MAKEPRIM_TO_F',` +static void +libelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap) +{ + Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src; + size_t c; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count * sizeof(*s)); + return; + } + + for (c = 0; c < count; c++) { + t = *s++; + SWAP_$1$3(t); + WRITE_$1$3(dst,t); + } +} +') + +define(`MAKEPRIM_TO_M',` +static void +libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap) +{ + Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst; + size_t c; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count * sizeof(*d)); + return; + } + + for (c = 0; c < count; c++) { + READ_$1$3(src,t); + SWAP_$1$3(t); + *d++ = t; + } +} +') + +define(`SWAP_FIELD', + `ifdef(`IGNORE_'$2,`', + `ifelse(BASE_$2,1, + `SWAP_$2(t.$1); + ', + `ifelse($2,BYTE,`', + `ifelse($2,IDENT,`', + `SWAP_$2'SZ()`(t.$1); + ')')')')') +define(`SWAP_MEMBERS', + `ifelse($#,1,`/**/', + `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') + +define(`SWAP_STRUCT', + `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ + SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') + +define(`WRITE_FIELD', + `ifelse(BASE_$2,1, + `WRITE_$2(dst,t.$1); + ', + `ifelse($2,IDENT, + `WRITE_$2(dst,t.$1); + ', + `WRITE_$2'SZ()`(dst,t.$1); + ')')') +define(`WRITE_MEMBERS', + `ifelse($#,1,`/**/', + `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') + +define(`WRITE_STRUCT', + `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ + WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') + +define(`READ_FIELD', + `ifelse(BASE_$2,1, + `READ_$2(s,t.$1); + ', + `ifelse($2,IDENT, + `READ_$2(s,t.$1); + ', + `READ_$2'SZ()`(s,t.$1); + ')')') + +define(`READ_MEMBERS', + `ifelse($#,1,`/**/', + `READ_FIELD($1)READ_MEMBERS(shift($@))')') + +define(`READ_STRUCT', + `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ + READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') + +/* + * Converters for non-integral ELF data structures. + * + * When converting data to file representation, the source pointer + * will be naturally aligned for a data structure's in-memory + * representation. When converting data to memory, the destination + * pointer will be similarly aligned. + * + * For in-place conversions, when converting to file representations, + * the source buffer is large enough to hold `file' data. When + * converting from file to memory, we need to be careful to work + * `backwards', to avoid overwriting unconverted data. + * + * Macro use: + * `$1': Name of the ELF type. + * `$2': C structure name suffix. + * `$3': ELF class specifier, one of [`', `32', `64'] + */ + +define(`MAKE_TO_F', + `ifdef(`IGNORE_'$1$3,`',` +static void +libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap) +{ + Elf$3_$2 t, *s; + size_t c; + + s = (Elf$3_$2 *) (uintptr_t) src; + for (c = 0; c < count; c++) { + t = *s++; + if (byteswap) { + SWAP_STRUCT($2,$3) + } + WRITE_STRUCT($2,$3) + } +} +')') + +define(`MAKE_TO_M', + `ifdef(`IGNORE_'$1$3,`',` +static void +libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap) +{ + Elf$3_$2 t, *d; + unsigned char *s,*s0; + size_t fsz; + + fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); + d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); + s0 = (unsigned char *) src + (count - 1) * fsz; + + while (count--) { + s = s0; + READ_STRUCT($2,$3) + if (byteswap) { + SWAP_STRUCT($2,$3) + } + *d-- = t; s0 -= fsz; + } +} +')') + +/* + * Make type convertor functions from the type definition + * of the ELF type: + * - if the type is a base (i.e., `primitive') type: + * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE) + * is defined, we skip the code generation step. + * - if the type is declared as `SIZEDEP', then 32 and 64 bit + * variants of the conversion functions are generated. + * - otherwise a 32 bit variant is generated. + * - if the type is a structure type, we generate 32 and 64 bit + * variants of the conversion functions. + */ + +define(`MAKE_TYPE_CONVERTER', + `ifdef(`BASE'_$1, + `ifdef(`IGNORE_'$1,`', + `MAKEPRIM_TO_F($1,$2,`',64) + MAKEPRIM_TO_M($1,$2,`',64)')', + `ifdef(`SIZEDEP_'$1, + `MAKEPRIM_TO_F($1,$2,32,32)dnl + MAKEPRIM_TO_M($1,$2,32,32)dnl + MAKEPRIM_TO_F($1,$2,64,64)dnl + MAKEPRIM_TO_M($1,$2,64,64)', + `MAKE_TO_F($1,$2,32)dnl + MAKE_TO_F($1,$2,64)dnl + MAKE_TO_M($1,$2,32)dnl + MAKE_TO_M($1,$2,64)')') +') + +define(`MAKE_TYPE_CONVERTERS', + `ifelse($#,1,`', + `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') + +divert(0) + +/* + * Sections of type ELF_T_BYTE are never byteswapped, consequently a + * simple memcpy suffices for both directions of conversion. + */ + +static void +libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap) +{ + (void) byteswap; + if (dst != src) + (void) memcpy(dst, src, count); +} + +/* + * Elf_Note structures comprise a fixed size header followed by variable + * length strings. The fixed size header needs to be byte swapped, but + * not the strings. + * + * Argument `count' denotes the total number of bytes to be converted. + */ +static void +libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap) +{ + uint32_t namesz, descsz, type; + Elf_Note *en; + size_t sz; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count); + return; + } + + while (count > sizeof(Elf_Note)) { + + READ_WORD(src, namesz); + READ_WORD(src, descsz); + READ_WORD(src, type); + + if (byteswap) { + SWAP_WORD(namesz); + SWAP_WORD(descsz); + SWAP_WORD(type); + } + + en = (Elf_Note *) (uintptr_t) dst; + en->n_namesz = namesz; + en->n_descsz = descsz; + en->n_type = type; + + dst += sizeof(Elf_Note); + + ROUNDUP2(namesz, 4); + ROUNDUP2(descsz, 4); + + sz = namesz + descsz; + + if (count < sz) + sz = count; + + (void) memcpy(dst, src, sz); + + src += sz; + dst += sz; + count -= sz; + } +} + +static void +libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap) +{ + uint32_t namesz, descsz, type; + Elf_Note *en; + size_t sz; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count); + return; + } + + while (count > sizeof(Elf_Note)) { + + en = (Elf_Note *) (uintptr_t) src; + namesz = en->n_namesz; + descsz = en->n_descsz; + type = en->n_type; + + if (byteswap) { + SWAP_WORD(namesz); + SWAP_WORD(descsz); + SWAP_WORD(type); + } + + + WRITE_WORD(dst, namesz); + WRITE_WORD(dst, descsz); + WRITE_WORD(dst, type); + + src += sizeof(Elf_Note); + + ROUNDUP2(namesz, 4); + ROUNDUP2(descsz, 4); + + sz = namesz + descsz; + + if (count < sz) + sz = count; + + (void) memcpy(dst, src, sz); + + src += sz; + dst += sz; + count -= sz; + } +} + +MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) + +struct converters { + void (*tof32)(char *dst, char *src, size_t cnt, int byteswap); + void (*tom32)(char *dst, char *src, size_t cnt, int byteswap); + void (*tof64)(char *dst, char *src, size_t cnt, int byteswap); + void (*tom64)(char *dst, char *src, size_t cnt, int byteswap); +}; + +divert(-1) +define(`CONV', + `ifdef(`IGNORE_'$1$2, + `.$3$2 = NULL', + `ifdef(`BASE_'$1, + `ifdef(`IGNORE_'$1, + `.$3$2 = NULL', + `.$3$2 = libelf_cvt_$1_$3')', + `ifdef(`SIZEDEP_'$1, + `.$3$2 = libelf_cvt_$1$2_$3', + `.$3$2 = libelf_cvt$2_$1_$3')')')') + +define(`CONVERTER_NAME', + `[ELF_T_$1] = { + CONV($1,32,tof), CONV($1,32,tom), + CONV($1,64,tof), CONV($1,64,tom) },')') + +define(`CONVERTER_NAMES', + `ifelse($#,1,`', + `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') + +undefine(`IGNORE_BYTE32') +undefine(`IGNORE_BYTE64') +divert(0) + +static struct converters cvt[ELF_T_NUM] = { +CONVERTER_NAMES(ELF_TYPE_LIST) + + /* + * Types that needs hand-coded converters follow. + */ + + [ELF_T_BYTE] = { + .tof32 = libelf_cvt_BYTE_tox, + .tom32 = libelf_cvt_BYTE_tox, + .tof64 = libelf_cvt_BYTE_tox, + .tom64 = libelf_cvt_BYTE_tox + }, + [ELF_T_NOTE] = { + .tof32 = libelf_cvt_NOTE_tof, + .tom32 = libelf_cvt_NOTE_tom, + .tof64 = libelf_cvt_NOTE_tof, + .tom64 = libelf_cvt_NOTE_tom + } +}; + +void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) + (char *_dst, char *_src, size_t _cnt, int _byteswap) +{ + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); + + if (t >= ELF_T_NUM || + (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || + (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) + return (NULL); + + return ((elfclass == ELFCLASS32) ? + (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : + (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); +} diff --git a/simulators/gem5/ext/libelf/libelf_data.c b/simulators/gem5/ext/libelf/libelf_data.c new file mode 100644 index 00000000..49c65754 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_data.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "libelf.h" + +#include "_libelf.h" + +int +_libelf_xlate_shtype(uint32_t sht) +{ + switch (sht) { + case SHT_DYNAMIC: + return (ELF_T_DYN); + case SHT_DYNSYM: + return (ELF_T_SYM); + case SHT_FINI_ARRAY: + return (ELF_T_ADDR); + case SHT_GROUP: + return (ELF_T_WORD); + case SHT_HASH: + return (ELF_T_WORD); + case SHT_INIT_ARRAY: + return (ELF_T_ADDR); + case SHT_NOBITS: + return (ELF_T_BYTE); + case SHT_NOTE: + return (ELF_T_NOTE); + case SHT_PREINIT_ARRAY: + return (ELF_T_ADDR); + case SHT_PROGBITS: + return (ELF_T_BYTE); + case SHT_REL: + return (ELF_T_REL); + case SHT_RELA: + return (ELF_T_RELA); + case SHT_STRTAB: + return (ELF_T_BYTE); + case SHT_SYMTAB: + return (ELF_T_SYM); + case SHT_SYMTAB_SHNDX: + return (ELF_T_WORD); + case SHT_GNU_verdef: /* == SHT_SUNW_verdef */ + return (ELF_T_VDEF); + case SHT_GNU_verneed: /* == SHT_SUNW_verneed */ + return (ELF_T_VNEED); + case SHT_GNU_versym: /* == SHT_SUNW_versym */ + return (-1); /* XXX */ + case SHT_SUNW_move: + return (ELF_T_MOVE); + case SHT_SUNW_syminfo: + return (ELF_T_SYMINFO); + default: + return (-1); + } +} diff --git a/simulators/gem5/ext/libelf/libelf_ehdr.c b/simulators/gem5/ext/libelf/libelf_ehdr.c new file mode 100644 index 00000000..c9039468 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_ehdr.c @@ -0,0 +1,201 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/libelf_ehdr.c,v 1.2 2006/12/25 02:22:22 jkoshy Exp $ + */ + +#include +#include "gelf.h" +#include "libelf.h" +#include + +#include "_libelf.h" + +/* + * Retrieve counts for sections, phdrs and the section string table index + * from section header #0 of the ELF object. + */ +static int +_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum, + uint16_t strndx) +{ + Elf_Scn *scn; + size_t fsz; + void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + uint32_t shtype; + + assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); + + fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1); + assert(fsz > 0); + + if (e->e_rawsize < shoff + fsz) { /* raw file too small */ + LIBELF_SET_ERROR(HEADER, 0); + return (0); + } + + if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL) + return (0); + + xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); + (*xlator)((char *) &scn->s_shdr, e->e_rawfile + shoff, (size_t) 1, + e->e_byteorder != LIBELF_PRIVATE(byteorder)); + +#define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \ + scn->s_shdr.s_shdr64.M) + + if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) { + LIBELF_SET_ERROR(SECTION, 0); + return (0); + } + + e->e_u.e_elf.e_nscn = GET_SHDR_MEMBER(sh_size); + e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum : + GET_SHDR_MEMBER(sh_info); + e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx : + GET_SHDR_MEMBER(sh_link); +#undef GET_SHDR_MEMBER + + return (1); +} + +#define EHDR_INIT(E,SZ) do { \ + Elf##SZ##_Ehdr *eh = (E); \ + eh->e_ident[EI_MAG0] = ELFMAG0; \ + eh->e_ident[EI_MAG1] = ELFMAG1; \ + eh->e_ident[EI_MAG2] = ELFMAG2; \ + eh->e_ident[EI_MAG3] = ELFMAG3; \ + eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \ + eh->e_ident[EI_DATA] = ELFDATANONE; \ + eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version); \ + eh->e_machine = EM_NONE; \ + eh->e_type = ELF_K_NONE; \ + eh->e_version = LIBELF_PRIVATE(version); \ + } while (0) + +void * +_libelf_ehdr(Elf *e, int ec, int allocate) +{ + void *ehdr; + size_t fsz, msz; + uint16_t phnum, shnum, strndx; + uint64_t shoff; + void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (e == NULL || e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (e->e_class != ELFCLASSNONE && e->e_class != ec) { + LIBELF_SET_ERROR(CLASS, 0); + return (NULL); + } + + if (e->e_version != EV_CURRENT) { + LIBELF_SET_ERROR(VERSION, 0); + return (NULL); + } + + if (e->e_class == ELFCLASSNONE) + e->e_class = ec; + + if (ec == ELFCLASS32) + ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32; + else + ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64; + + if (ehdr != NULL) /* already have a translated ehdr */ + return (ehdr); + + fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); + assert(fsz > 0); + + if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) { + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT); + + assert(msz > 0); + + if ((ehdr = calloc((size_t) 1, msz)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr; + EHDR_INIT(ehdr,32); + } else { + e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr; + EHDR_INIT(ehdr,64); + } + + if (allocate) + e->e_flags |= ELF_F_DIRTY; + + if (e->e_cmd == ELF_C_WRITE) + return (ehdr); + + xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec); + (*xlator)(ehdr, e->e_rawfile, (size_t) 1, + e->e_byteorder != LIBELF_PRIVATE(byteorder)); + + /* + * If extended numbering is being used, read the correct + * number of sections and program header entries. + */ + if (ec == ELFCLASS32) { + phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; + shnum = ((Elf32_Ehdr *) ehdr)->e_shnum; + shoff = ((Elf32_Ehdr *) ehdr)->e_shoff; + strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx; + } else { + phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; + shnum = ((Elf64_Ehdr *) ehdr)->e_shnum; + shoff = ((Elf64_Ehdr *) ehdr)->e_shoff; + strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx; + } + + if (shnum >= SHN_LORESERVE || + (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM || + strndx == SHN_XINDEX))) { + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */ + e->e_u.e_elf.e_nphdr = phnum; + e->e_u.e_elf.e_nscn = shnum; + e->e_u.e_elf.e_strndx = strndx; + } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0) + return (NULL); + + return (ehdr); +} diff --git a/simulators/gem5/ext/libelf/libelf_extended.c b/simulators/gem5/ext/libelf/libelf_extended.c new file mode 100644 index 00000000..01363aaf --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_extended.c @@ -0,0 +1,133 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "libelf.h" + +#include "_libelf.h" + +/* + * Retrieve section #0, allocating a new section if needed. + */ +static Elf_Scn * +_libelf_getscn0(Elf *e) +{ + Elf_Scn *s; + + if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL) + return (s); + + return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF)); +} + +int +_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum) +{ + Elf_Scn *scn; + + if (shnum >= SHN_LORESERVE) { + if ((scn = _libelf_getscn0(e)) == NULL) + return (0); + + assert(scn->s_ndx == SHN_UNDEF); + + if (ec == ELFCLASS32) + scn->s_shdr.s_shdr32.sh_size = shnum; + else + scn->s_shdr.s_shdr64.sh_size = shnum; + + (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); + + shnum = 0; + } + + if (ec == ELFCLASS32) + ((Elf32_Ehdr *) eh)->e_shnum = shnum; + else + ((Elf64_Ehdr *) eh)->e_shnum = shnum; + + + return (1); +} + +int +_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx) +{ + Elf_Scn *scn; + + if (shstrndx >= SHN_LORESERVE) { + if ((scn = _libelf_getscn0(e)) == NULL) + return (0); + + assert(scn->s_ndx == SHN_UNDEF); + + if (ec == ELFCLASS32) + scn->s_shdr.s_shdr32.sh_link = shstrndx; + else + scn->s_shdr.s_shdr64.sh_link = shstrndx; + + (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); + + shstrndx = SHN_XINDEX; + } + + if (ec == ELFCLASS32) + ((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx; + else + ((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx; + + return (1); +} + +int +_libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum) +{ + Elf_Scn *scn; + + if (phnum >= PN_XNUM) { + if ((scn = _libelf_getscn0(e)) == NULL) + return (0); + + assert(scn->s_ndx == SHN_UNDEF); + + if (ec == ELFCLASS32) + scn->s_shdr.s_shdr32.sh_info = phnum; + else + scn->s_shdr.s_shdr64.sh_info = phnum; + + (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); + + phnum = PN_XNUM; + } + + if (ec == ELFCLASS32) + ((Elf32_Ehdr *) eh)->e_phnum = phnum; + else + ((Elf64_Ehdr *) eh)->e_phnum = phnum; + + return (1); +} + diff --git a/simulators/gem5/ext/libelf/libelf_fsize.m4 b/simulators/gem5/ext/libelf/libelf_fsize.m4 new file mode 100644 index 00000000..fa4657b3 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_fsize.m4 @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/libelf_fsize.m4,v 1.2 2006/12/18 05:40:01 jkoshy Exp $ + */ + +#include "libelf.h" +#include "_libelf.h" + +/* + * Create an array of file sizes from the elf_type definitions + */ + +divert(-1) +include(SRCDIR`/elf_types.m4') + +/* + * Translations from structure definitions to the size of their file + * representations. + */ + +/* `Basic' types */ +define(`BYTE_SIZE', 1) +define(`IDENT_SIZE', `EI_NIDENT') +define(`NOTE_SIZE', 1) /* Elf_Note structures have variable length. */ + +/* Currently unimplemented types */ +define(`MOVEP_SIZE', 0) + +/* Overrides for 32 bit types that do not exist */ +define(`XWORD_SIZE32', 0) +define(`SXWORD_SIZE32', 0) + +/* + * FSZ{32,64} define the sizes of 32 and 64 bit file structures respectively. + */ + +define(`FSZ32',`_FSZ32($1_DEF)') +define(`_FSZ32', + `ifelse($#,1,0, + `_BSZ32($1)+_FSZ32(shift($@))')') +define(`_BSZ32',`$2_SIZE32') + +define(`FSZ64',`_FSZ64($1_DEF)') +define(`_FSZ64', + `ifelse($#,1,0, + `_BSZ64($1)+_FSZ64(shift($@))')') +define(`_BSZ64',`$2_SIZE64') + +/* + * DEFINE_ELF_FSIZES(TYPE,NAME) + * + * Shorthand for defining for 32 and 64 versions + * of elf type TYPE. + * + * If TYPE`'_SIZE is defined, use its value for both 32 bit and 64 bit + * sizes. + * + * Otherwise, look for a explicit 32/64 bit size definition for TYPE, + * TYPE`'_SIZE32 or TYPE`'_SIZE64. If this definition is present, there + * is nothing further to do. + * + * Otherwise, if an Elf{32,64}_`'NAME structure definition is known, + * compute an expression that adds up the sizes of the structure's + * constituents. + * + * If such a structure definition is not known, treat TYPE as a primitive + * (i.e., integral) type and use sizeof(Elf{32,64}_`'NAME) to get its + * file representation size. + */ + +define(`DEFINE_ELF_FSIZE', + `ifdef($1`_SIZE', + `define($1_SIZE32,$1_SIZE) + define($1_SIZE64,$1_SIZE)', + `ifdef($1`_SIZE32',`', + `ifdef(`Elf32_'$2`_DEF', + `define($1_SIZE32,FSZ32(Elf32_$2))', + `define($1_SIZE32,`sizeof(Elf32_'$2`)')')') + ifdef($1`_SIZE64',`', + `ifdef(`Elf64_'$2`_DEF', + `define($1_SIZE64,FSZ64(Elf64_$2))', + `define($1_SIZE64,`sizeof(Elf64_'$2`)')')')')') + +define(`DEFINE_ELF_FSIZES', + `ifelse($#,1,`', + `DEFINE_ELF_FSIZE($1) + DEFINE_ELF_FSIZES(shift($@))')') + +DEFINE_ELF_FSIZES(ELF_TYPE_LIST) +DEFINE_ELF_FSIZE(`IDENT',`') # `IDENT' is a pseudo type + +define(`FSIZE', + `[ELF_T_$1] = { .fsz32 = $1_SIZE32, .fsz64 = $1_SIZE64 },') +define(`FSIZES', + `ifelse($#,1,`', + `FSIZE($1) +FSIZES(shift($@))')') + +divert(0) + +struct fsize { + size_t fsz32; + size_t fsz64; +}; + +static struct fsize fsize[ELF_T_NUM] = { +FSIZES(ELF_TYPE_LIST) +}; + +size_t +_libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c) +{ + size_t sz; + + sz = 0; + if (v != EV_CURRENT) + LIBELF_SET_ERROR(VERSION, 0); + else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST) + LIBELF_SET_ERROR(ARGUMENT, 0); + else { + sz = ec == ELFCLASS64 ? fsize[t].fsz64 : fsize[t].fsz32; + if (sz == 0) + LIBELF_SET_ERROR(UNIMPL, 0); + } + + return (sz*c); +} + diff --git a/simulators/gem5/ext/libelf/libelf_msize.m4 b/simulators/gem5/ext/libelf/libelf_msize.m4 new file mode 100644 index 00000000..cca31679 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_msize.m4 @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include + +#include "elf32.h" +#include "elf64.h" +#include "libelf.h" +#include "_libelf.h" + +/* WARNING: GENERATED FROM __file__. */ + +struct msize { + size_t msz32; + size_t msz64; +}; + +divert(-1) +include(SRCDIR`/elf_types.m4') + +define(BYTE_SIZE, 1) +define(NOTE_SIZE, 1) + +/* + * Unimplemented types. + */ +define(MOVEP_SIZE, 0) +define(SXWORD_SIZE32, 0) +define(XWORD_SIZE32, 0) + +define(`DEFINE_ELF_MSIZE', + `ifdef($1`_SIZE', + `define($1_SIZE32,$1_SIZE) + define($1_SIZE64,$1_SIZE)', + `ifdef($1`_SIZE32',`', + `define($1_SIZE32,sizeof(Elf32_$2))') + ifdef($1`_SIZE64',`', + `define($1_SIZE64,sizeof(Elf64_$2))')')') +define(`DEFINE_ELF_MSIZES', + `ifelse($#,1,`', + `DEFINE_ELF_MSIZE($1) + DEFINE_ELF_MSIZES(shift($@))')') + +DEFINE_ELF_MSIZES(ELF_TYPE_LIST) + +define(`MSIZE', + `[ELF_T_$1] = { .msz32 = $1_SIZE32, .msz64 = $1_SIZE64 },') +define(`MSIZES', + `ifelse($#,1,`', + `MSIZE($1) +MSIZES(shift($@))')') + +divert(0) + +static struct msize msize[ELF_T_NUM] = { +MSIZES(ELF_TYPE_LIST) +}; + +size_t +_libelf_msize(Elf_Type t, int elfclass, unsigned int version) +{ + size_t sz; + + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST); + + if (version != EV_CURRENT) { + LIBELF_SET_ERROR(VERSION, 0); + return (0); + } + + sz = (elfclass == ELFCLASS32) ? msize[t].msz32 : msize[t].msz64; + + return (sz); +} diff --git a/simulators/gem5/ext/libelf/libelf_phdr.c b/simulators/gem5/ext/libelf/libelf_phdr.c new file mode 100644 index 00000000..1d7e90bc --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_phdr.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libelf/libelf_phdr.c,v 1.2 2006/12/25 02:22:22 jkoshy Exp $ + */ + +#include +#include + +#include "gelf.h" +#include "libelf.h" +#include "_libelf.h" + +void * +_libelf_getphdr(Elf *e, int ec) +{ + size_t phnum, phentsize; + size_t fsz, msz; + uint64_t phoff; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + void *ehdr, *phdr; + void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((phdr = (ec == ELFCLASS32 ? + (void *) e->e_u.e_elf.e_phdr.e_phdr32 : + (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL) + return (phdr); + + /* + * Check the PHDR related fields in the EHDR for sanity. + */ + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (NULL); + + phnum = e->e_u.e_elf.e_nphdr; + + if (ec == ELFCLASS32) { + eh32 = (Elf32_Ehdr *) ehdr; + phentsize = eh32->e_phentsize; + phoff = (uint64_t) eh32->e_phoff; + } else { + eh64 = (Elf64_Ehdr *) ehdr; + phentsize = eh64->e_phentsize; + phoff = (uint64_t) eh64->e_phoff; + } + + fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version); + + assert(fsz > 0); + + if ((uint64_t) e->e_rawsize < (phoff + fsz)) { + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT); + + assert(msz > 0); + + if ((phdr = calloc(phnum, msz)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + if (ec == ELFCLASS32) + e->e_u.e_elf.e_phdr.e_phdr32 = phdr; + else + e->e_u.e_elf.e_phdr.e_phdr64 = phdr; + + + xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec); + (*xlator)(phdr, e->e_rawfile + phoff, phnum, + e->e_byteorder != LIBELF_PRIVATE(byteorder)); + + return (phdr); +} + +void * +_libelf_newphdr(Elf *e, int ec, size_t count) +{ + void *ehdr, *newphdr, *oldphdr; + size_t msz; + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + assert(e->e_class == ec); + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + assert(e->e_version == EV_CURRENT); + + msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version); + + assert(msz > 0); + + newphdr = NULL; + if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) + free(oldphdr); + e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr; + } else { + if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) + free(oldphdr); + e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr; + } + + e->e_u.e_elf.e_nphdr = count; + + elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (newphdr); +} diff --git a/simulators/gem5/ext/libelf/libelf_shdr.c b/simulators/gem5/ext/libelf/libelf_shdr.c new file mode 100644 index 00000000..c1e14071 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_shdr.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gelf.h" +#include "libelf.h" +#include "_libelf.h" + +void * +_libelf_getshdr(Elf_Scn *s, int ec) +{ + Elf *e; + + if (s == NULL || (e = s->s_elf) == NULL || + e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASSNONE) + ec = e->e_class; + + if (ec != e->e_class) { + LIBELF_SET_ERROR(CLASS, 0); + return (NULL); + } + + return ((void *) &s->s_shdr); +} diff --git a/simulators/gem5/ext/libelf/libelf_xlate.c b/simulators/gem5/ext/libelf/libelf_xlate.c new file mode 100644 index 00000000..c5fea208 --- /dev/null +++ b/simulators/gem5/ext/libelf/libelf_xlate.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "libelf.h" +#include "_libelf.h" + +/* + * Translate to/from the file representation of ELF objects. + * + * Translation could potentially involve the following + * transformations: + * + * - an endianness conversion, + * - a change of layout, as the file representation of ELF objects + * can differ from their in-memory representation. + * - a change in representation due to a layout version change. + */ + +Elf_Data * +_libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, + int elfclass, int direction) +{ + size_t cnt, dsz, fsz, msz; + uintptr_t sb, se, db, de; + + if (encoding == ELFDATANONE) + encoding = LIBELF_PRIVATE(byteorder); + + if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) || + dst == NULL || src == NULL || dst == src) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); + + if (dst->d_version != src->d_version) { + LIBELF_SET_ERROR(UNIMPL, 0); + return (NULL); + } + + if (src->d_buf == NULL || dst->d_buf == NULL || + src->d_size == 0) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)(src->d_type, + (size_t) 1, src->d_version)) == 0) + return (NULL); + + msz = _libelf_msize(src->d_type, elfclass, src->d_version); + + assert(msz > 0); + + if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + /* + * Determine the number of objects that need to be converted, and + * the space required for the converted objects in the destination + * buffer. + */ + if (direction == ELF_TOMEMORY) { + cnt = src->d_size / fsz; + dsz = cnt * msz; + } else { + cnt = src->d_size / msz; + dsz = cnt * fsz; + } + + if (dst->d_size < dsz) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + sb = (uintptr_t) src->d_buf; + se = sb + src->d_size; + db = (uintptr_t) dst->d_buf; + de = db + dst->d_size; + + /* + * Check for overlapping buffers. Note that db == sb is + * allowed. + */ + if (db != sb && de > sb && se > db) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((direction == ELF_TOMEMORY ? db : sb) % + _libelf_malign(src->d_type, elfclass)) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + dst->d_type = src->d_type; + dst->d_size = dsz; + + if (db == sb && encoding == LIBELF_PRIVATE(byteorder) && + fsz == msz) + return (dst); /* nothing more to do */ + + (_libelf_get_translator(src->d_type, direction, elfclass))(dst->d_buf, + src->d_buf, cnt, encoding != LIBELF_PRIVATE(byteorder)); + + return (dst); +} diff --git a/simulators/gem5/ext/ply/ANNOUNCE b/simulators/gem5/ext/ply/ANNOUNCE new file mode 100644 index 00000000..0a155cec --- /dev/null +++ b/simulators/gem5/ext/ply/ANNOUNCE @@ -0,0 +1,41 @@ +March 24, 2009 + + Announcing : PLY-3.2 (Python Lex-Yacc) + + http://www.dabeaz.com/ply + +I'm pleased to announce a significant new update to PLY---a 100% Python +implementation of the common parsing tools lex and yacc. PLY-3.2 adds +compatibility for Python 2.6 and 3.0, provides some new customization +options, and cleans up a lot of internal implementation details. + +If you are new to PLY, here are a few highlights: + +- PLY is closely modeled after traditional lex/yacc. If you know how + to use these or similar tools in other languages, you will find + PLY to be comparable. + +- PLY provides very extensive error reporting and diagnostic + information to assist in parser construction. The original + implementation was developed for instructional purposes. As + a result, the system tries to identify the most common types + of errors made by novice users. + +- PLY provides full support for empty productions, error recovery, + precedence rules, and ambiguous grammars. + +- Parsing is based on LR-parsing which is fast, memory efficient, + better suited to large grammars, and which has a number of nice + properties when dealing with syntax errors and other parsing + problems. Currently, PLY can build its parsing tables using + either SLR or LALR(1) algorithms. + +More information about PLY can be obtained on the PLY webpage at: + + http://www.dabeaz.com/ply + +PLY is freely available. + +Cheers, + +David Beazley (http://www.dabeaz.com) \ No newline at end of file diff --git a/simulators/gem5/ext/ply/CHANGES b/simulators/gem5/ext/ply/CHANGES new file mode 100644 index 00000000..9d8b25d5 --- /dev/null +++ b/simulators/gem5/ext/ply/CHANGES @@ -0,0 +1,1069 @@ + +Version 3.2 +----------------------------- +03/24/09: beazley + Added an extra check to not print duplicated warning messages + about reduce/reduce conflicts. + +03/24/09: beazley + Switched PLY over to a BSD-license. + +03/23/09: beazley + Performance optimization. Discovered a few places to make + speedups in LR table generation. + +03/23/09: beazley + New warning message. PLY now warns about rules never + reduced due to reduce/reduce conflicts. Suggested by + Bruce Frederiksen. + +03/23/09: beazley + Some clean-up of warning messages related to reduce/reduce errors. + +03/23/09: beazley + Added a new picklefile option to yacc() to write the parsing + tables to a filename using the pickle module. Here is how + it works: + + yacc(picklefile="parsetab.p") + + This option can be used if the normal parsetab.py file is + extremely large. For example, on jython, it is impossible + to read parsing tables if the parsetab.py exceeds a certain + threshold. + + The filename supplied to the picklefile option is opened + relative to the current working directory of the Python + interpreter. If you need to refer to the file elsewhere, + you will need to supply an absolute or relative path. + + For maximum portability, the pickle file is written + using protocol 0. + +03/13/09: beazley + Fixed a bug in parser.out generation where the rule numbers + where off by one. + +03/13/09: beazley + Fixed a string formatting bug with one of the error messages. + Reported by Richard Reitmeyer + +Version 3.1 +----------------------------- +02/28/09: beazley + Fixed broken start argument to yacc(). PLY-3.0 broke this + feature by accident. + +02/28/09: beazley + Fixed debugging output. yacc() no longer reports shift/reduce + or reduce/reduce conflicts if debugging is turned off. This + restores similar behavior in PLY-2.5. Reported by Andrew Waters. + +Version 3.0 +----------------------------- +02/03/09: beazley + Fixed missing lexer attribute on certain tokens when + invoking the parser p_error() function. Reported by + Bart Whiteley. + +02/02/09: beazley + The lex() command now does all error-reporting and diagonistics + using the logging module interface. Pass in a Logger object + using the errorlog parameter to specify a different logger. + +02/02/09: beazley + Refactored ply.lex to use a more object-oriented and organized + approach to collecting lexer information. + +02/01/09: beazley + Removed the nowarn option from lex(). All output is controlled + by passing in a logger object. Just pass in a logger with a high + level setting to suppress output. This argument was never + documented to begin with so hopefully no one was relying upon it. + +02/01/09: beazley + Discovered and removed a dead if-statement in the lexer. This + resulted in a 6-7% speedup in lexing when I tested it. + +01/13/09: beazley + Minor change to the procedure for signalling a syntax error in a + production rule. A normal SyntaxError exception should be raised + instead of yacc.SyntaxError. + +01/13/09: beazley + Added a new method p.set_lineno(n,lineno) that can be used to set the + line number of symbol n in grammar rules. This simplifies manual + tracking of line numbers. + +01/11/09: beazley + Vastly improved debugging support for yacc.parse(). Instead of passing + debug as an integer, you can supply a Logging object (see the logging + module). Messages will be generated at the ERROR, INFO, and DEBUG + logging levels, each level providing progressively more information. + The debugging trace also shows states, grammar rule, values passed + into grammar rules, and the result of each reduction. + +01/09/09: beazley + The yacc() command now does all error-reporting and diagnostics using + the interface of the logging module. Use the errorlog parameter to + specify a logging object for error messages. Use the debuglog parameter + to specify a logging object for the 'parser.out' output. + +01/09/09: beazley + *HUGE* refactoring of the the ply.yacc() implementation. The high-level + user interface is backwards compatible, but the internals are completely + reorganized into classes. No more global variables. The internals + are also more extensible. For example, you can use the classes to + construct a LALR(1) parser in an entirely different manner than + what is currently the case. Documentation is forthcoming. + +01/07/09: beazley + Various cleanup and refactoring of yacc internals. + +01/06/09: beazley + Fixed a bug with precedence assignment. yacc was assigning the precedence + each rule based on the left-most token, when in fact, it should have been + using the right-most token. Reported by Bruce Frederiksen. + +11/27/08: beazley + Numerous changes to support Python 3.0 including removal of deprecated + statements (e.g., has_key) and the additional of compatibility code + to emulate features from Python 2 that have been removed, but which + are needed. Fixed the unit testing suite to work with Python 3.0. + The code should be backwards compatible with Python 2. + +11/26/08: beazley + Loosened the rules on what kind of objects can be passed in as the + "module" parameter to lex() and yacc(). Previously, you could only use + a module or an instance. Now, PLY just uses dir() to get a list of + symbols on whatever the object is without regard for its type. + +11/26/08: beazley + Changed all except: statements to be compatible with Python2.x/3.x syntax. + +11/26/08: beazley + Changed all raise Exception, value statements to raise Exception(value) for + forward compatibility. + +11/26/08: beazley + Removed all print statements from lex and yacc, using sys.stdout and sys.stderr + directly. Preparation for Python 3.0 support. + +11/04/08: beazley + Fixed a bug with referring to symbols on the the parsing stack using negative + indices. + +05/29/08: beazley + Completely revamped the testing system to use the unittest module for everything. + Added additional tests to cover new errors/warnings. + +Version 2.5 +----------------------------- +05/28/08: beazley + Fixed a bug with writing lex-tables in optimized mode and start states. + Reported by Kevin Henry. + +Version 2.4 +----------------------------- +05/04/08: beazley + A version number is now embedded in the table file signature so that + yacc can more gracefully accomodate changes to the output format + in the future. + +05/04/08: beazley + Removed undocumented .pushback() method on grammar productions. I'm + not sure this ever worked and can't recall ever using it. Might have + been an abandoned idea that never really got fleshed out. This + feature was never described or tested so removing it is hopefully + harmless. + +05/04/08: beazley + Added extra error checking to yacc() to detect precedence rules defined + for undefined terminal symbols. This allows yacc() to detect a potential + problem that can be really tricky to debug if no warning message or error + message is generated about it. + +05/04/08: beazley + lex() now has an outputdir that can specify the output directory for + tables when running in optimize mode. For example: + + lexer = lex.lex(optimize=True, lextab="ltab", outputdir="foo/bar") + + The behavior of specifying a table module and output directory are + more aligned with the behavior of yacc(). + +05/04/08: beazley + [Issue 9] + Fixed filename bug in when specifying the modulename in lex() and yacc(). + If you specified options such as the following: + + parser = yacc.yacc(tabmodule="foo.bar.parsetab",outputdir="foo/bar") + + yacc would create a file "foo.bar.parsetab.py" in the given directory. + Now, it simply generates a file "parsetab.py" in that directory. + Bug reported by cptbinho. + +05/04/08: beazley + Slight modification to lex() and yacc() to allow their table files + to be loaded from a previously loaded module. This might make + it easier to load the parsing tables from a complicated package + structure. For example: + + import foo.bar.spam.parsetab as parsetab + parser = yacc.yacc(tabmodule=parsetab) + + Note: lex and yacc will never regenerate the table file if used + in the form---you will get a warning message instead. + This idea suggested by Brian Clapper. + + +04/28/08: beazley + Fixed a big with p_error() functions being picked up correctly + when running in yacc(optimize=1) mode. Patch contributed by + Bart Whiteley. + +02/28/08: beazley + Fixed a bug with 'nonassoc' precedence rules. Basically the + non-precedence was being ignored and not producing the correct + run-time behavior in the parser. + +02/16/08: beazley + Slight relaxation of what the input() method to a lexer will + accept as a string. Instead of testing the input to see + if the input is a string or unicode string, it checks to see + if the input object looks like it contains string data. + This change makes it possible to pass string-like objects + in as input. For example, the object returned by mmap. + + import mmap, os + data = mmap.mmap(os.open(filename,os.O_RDONLY), + os.path.getsize(filename), + access=mmap.ACCESS_READ) + lexer.input(data) + + +11/29/07: beazley + Modification of ply.lex to allow token functions to aliased. + This is subtle, but it makes it easier to create libraries and + to reuse token specifications. For example, suppose you defined + a function like this: + + def number(t): + r'\d+' + t.value = int(t.value) + return t + + This change would allow you to define a token rule as follows: + + t_NUMBER = number + + In this case, the token type will be set to 'NUMBER' and use + the associated number() function to process tokens. + +11/28/07: beazley + Slight modification to lex and yacc to grab symbols from both + the local and global dictionaries of the caller. This + modification allows lexers and parsers to be defined using + inner functions and closures. + +11/28/07: beazley + Performance optimization: The lexer.lexmatch and t.lexer + attributes are no longer set for lexer tokens that are not + defined by functions. The only normal use of these attributes + would be in lexer rules that need to perform some kind of + special processing. Thus, it doesn't make any sense to set + them on every token. + + *** POTENTIAL INCOMPATIBILITY *** This might break code + that is mucking around with internal lexer state in some + sort of magical way. + +11/27/07: beazley + Added the ability to put the parser into error-handling mode + from within a normal production. To do this, simply raise + a yacc.SyntaxError exception like this: + + def p_some_production(p): + 'some_production : prod1 prod2' + ... + raise yacc.SyntaxError # Signal an error + + A number of things happen after this occurs: + + - The last symbol shifted onto the symbol stack is discarded + and parser state backed up to what it was before the + the rule reduction. + + - The current lookahead symbol is saved and replaced by + the 'error' symbol. + + - The parser enters error recovery mode where it tries + to either reduce the 'error' rule or it starts + discarding items off of the stack until the parser + resets. + + When an error is manually set, the parser does *not* call + the p_error() function (if any is defined). + *** NEW FEATURE *** Suggested on the mailing list + +11/27/07: beazley + Fixed structure bug in examples/ansic. Reported by Dion Blazakis. + +11/27/07: beazley + Fixed a bug in the lexer related to start conditions and ignored + token rules. If a rule was defined that changed state, but + returned no token, the lexer could be left in an inconsistent + state. Reported by + +11/27/07: beazley + Modified setup.py to support Python Eggs. Patch contributed by + Simon Cross. + +11/09/07: beazely + Fixed a bug in error handling in yacc. If a syntax error occurred and the + parser rolled the entire parse stack back, the parser would be left in in + inconsistent state that would cause it to trigger incorrect actions on + subsequent input. Reported by Ton Biegstraaten, Justin King, and others. + +11/09/07: beazley + Fixed a bug when passing empty input strings to yacc.parse(). This + would result in an error message about "No input given". Reported + by Andrew Dalke. + +Version 2.3 +----------------------------- +02/20/07: beazley + Fixed a bug with character literals if the literal '.' appeared as the + last symbol of a grammar rule. Reported by Ales Smrcka. + +02/19/07: beazley + Warning messages are now redirected to stderr instead of being printed + to standard output. + +02/19/07: beazley + Added a warning message to lex.py if it detects a literal backslash + character inside the t_ignore declaration. This is to help + problems that might occur if someone accidentally defines t_ignore + as a Python raw string. For example: + + t_ignore = r' \t' + + The idea for this is from an email I received from David Cimimi who + reported bizarre behavior in lexing as a result of defining t_ignore + as a raw string by accident. + +02/18/07: beazley + Performance improvements. Made some changes to the internal + table organization and LR parser to improve parsing performance. + +02/18/07: beazley + Automatic tracking of line number and position information must now be + enabled by a special flag to parse(). For example: + + yacc.parse(data,tracking=True) + + In many applications, it's just not that important to have the + parser automatically track all line numbers. By making this an + optional feature, it allows the parser to run significantly faster + (more than a 20% speed increase in many cases). Note: positional + information is always available for raw tokens---this change only + applies to positional information associated with nonterminal + grammar symbols. + *** POTENTIAL INCOMPATIBILITY *** + +02/18/07: beazley + Yacc no longer supports extended slices of grammar productions. + However, it does support regular slices. For example: + + def p_foo(p): + '''foo: a b c d e''' + p[0] = p[1:3] + + This change is a performance improvement to the parser--it streamlines + normal access to the grammar values since slices are now handled in + a __getslice__() method as opposed to __getitem__(). + +02/12/07: beazley + Fixed a bug in the handling of token names when combined with + start conditions. Bug reported by Todd O'Bryan. + +Version 2.2 +------------------------------ +11/01/06: beazley + Added lexpos() and lexspan() methods to grammar symbols. These + mirror the same functionality of lineno() and linespan(). For + example: + + def p_expr(p): + 'expr : expr PLUS expr' + p.lexpos(1) # Lexing position of left-hand-expression + p.lexpos(1) # Lexing position of PLUS + start,end = p.lexspan(3) # Lexing range of right hand expression + +11/01/06: beazley + Minor change to error handling. The recommended way to skip characters + in the input is to use t.lexer.skip() as shown here: + + def t_error(t): + print "Illegal character '%s'" % t.value[0] + t.lexer.skip(1) + + The old approach of just using t.skip(1) will still work, but won't + be documented. + +10/31/06: beazley + Discarded tokens can now be specified as simple strings instead of + functions. To do this, simply include the text "ignore_" in the + token declaration. For example: + + t_ignore_cppcomment = r'//.*' + + Previously, this had to be done with a function. For example: + + def t_ignore_cppcomment(t): + r'//.*' + pass + + If start conditions/states are being used, state names should appear + before the "ignore_" text. + +10/19/06: beazley + The Lex module now provides support for flex-style start conditions + as described at http://www.gnu.org/software/flex/manual/html_chapter/flex_11.html. + Please refer to this document to understand this change note. Refer to + the PLY documentation for PLY-specific explanation of how this works. + + To use start conditions, you first need to declare a set of states in + your lexer file: + + states = ( + ('foo','exclusive'), + ('bar','inclusive') + ) + + This serves the same role as the %s and %x specifiers in flex. + + One a state has been declared, tokens for that state can be + declared by defining rules of the form t_state_TOK. For example: + + t_PLUS = '\+' # Rule defined in INITIAL state + t_foo_NUM = '\d+' # Rule defined in foo state + t_bar_NUM = '\d+' # Rule defined in bar state + + t_foo_bar_NUM = '\d+' # Rule defined in both foo and bar + t_ANY_NUM = '\d+' # Rule defined in all states + + In addition to defining tokens for each state, the t_ignore and t_error + specifications can be customized for specific states. For example: + + t_foo_ignore = " " # Ignored characters for foo state + def t_bar_error(t): + # Handle errors in bar state + + With token rules, the following methods can be used to change states + + def t_TOKNAME(t): + t.lexer.begin('foo') # Begin state 'foo' + t.lexer.push_state('foo') # Begin state 'foo', push old state + # onto a stack + t.lexer.pop_state() # Restore previous state + t.lexer.current_state() # Returns name of current state + + These methods mirror the BEGIN(), yy_push_state(), yy_pop_state(), and + yy_top_state() functions in flex. + + The use of start states can be used as one way to write sub-lexers. + For example, the lexer or parser might instruct the lexer to start + generating a different set of tokens depending on the context. + + example/yply/ylex.py shows the use of start states to grab C/C++ + code fragments out of traditional yacc specification files. + + *** NEW FEATURE *** Suggested by Daniel Larraz with whom I also + discussed various aspects of the design. + +10/19/06: beazley + Minor change to the way in which yacc.py was reporting shift/reduce + conflicts. Although the underlying LALR(1) algorithm was correct, + PLY was under-reporting the number of conflicts compared to yacc/bison + when precedence rules were in effect. This change should make PLY + report the same number of conflicts as yacc. + +10/19/06: beazley + Modified yacc so that grammar rules could also include the '-' + character. For example: + + def p_expr_list(p): + 'expression-list : expression-list expression' + + Suggested by Oldrich Jedlicka. + +10/18/06: beazley + Attribute lexer.lexmatch added so that token rules can access the re + match object that was generated. For example: + + def t_FOO(t): + r'some regex' + m = t.lexer.lexmatch + # Do something with m + + + This may be useful if you want to access named groups specified within + the regex for a specific token. Suggested by Oldrich Jedlicka. + +10/16/06: beazley + Changed the error message that results if an illegal character + is encountered and no default error function is defined in lex. + The exception is now more informative about the actual cause of + the error. + +Version 2.1 +------------------------------ +10/02/06: beazley + The last Lexer object built by lex() can be found in lex.lexer. + The last Parser object built by yacc() can be found in yacc.parser. + +10/02/06: beazley + New example added: examples/yply + + This example uses PLY to convert Unix-yacc specification files to + PLY programs with the same grammar. This may be useful if you + want to convert a grammar from bison/yacc to use with PLY. + +10/02/06: beazley + Added support for a start symbol to be specified in the yacc + input file itself. Just do this: + + start = 'name' + + where 'name' matches some grammar rule. For example: + + def p_name(p): + 'name : A B C' + ... + + This mirrors the functionality of the yacc %start specifier. + +09/30/06: beazley + Some new examples added.: + + examples/GardenSnake : A simple indentation based language similar + to Python. Shows how you might handle + whitespace. Contributed by Andrew Dalke. + + examples/BASIC : An implementation of 1964 Dartmouth BASIC. + Contributed by Dave against his better + judgement. + +09/28/06: beazley + Minor patch to allow named groups to be used in lex regular + expression rules. For example: + + t_QSTRING = r'''(?P['"]).*?(?P=quote)''' + + Patch submitted by Adam Ring. + +09/28/06: beazley + LALR(1) is now the default parsing method. To use SLR, use + yacc.yacc(method="SLR"). Note: there is no performance impact + on parsing when using LALR(1) instead of SLR. However, constructing + the parsing tables will take a little longer. + +09/26/06: beazley + Change to line number tracking. To modify line numbers, modify + the line number of the lexer itself. For example: + + def t_NEWLINE(t): + r'\n' + t.lexer.lineno += 1 + + This modification is both cleanup and a performance optimization. + In past versions, lex was monitoring every token for changes in + the line number. This extra processing is unnecessary for a vast + majority of tokens. Thus, this new approach cleans it up a bit. + + *** POTENTIAL INCOMPATIBILITY *** + You will need to change code in your lexer that updates the line + number. For example, "t.lineno += 1" becomes "t.lexer.lineno += 1" + +09/26/06: beazley + Added the lexing position to tokens as an attribute lexpos. This + is the raw index into the input text at which a token appears. + This information can be used to compute column numbers and other + details (e.g., scan backwards from lexpos to the first newline + to get a column position). + +09/25/06: beazley + Changed the name of the __copy__() method on the Lexer class + to clone(). This is used to clone a Lexer object (e.g., if + you're running different lexers at the same time). + +09/21/06: beazley + Limitations related to the use of the re module have been eliminated. + Several users reported problems with regular expressions exceeding + more than 100 named groups. To solve this, lex.py is now capable + of automatically splitting its master regular regular expression into + smaller expressions as needed. This should, in theory, make it + possible to specify an arbitrarily large number of tokens. + +09/21/06: beazley + Improved error checking in lex.py. Rules that match the empty string + are now rejected (otherwise they cause the lexer to enter an infinite + loop). An extra check for rules containing '#' has also been added. + Since lex compiles regular expressions in verbose mode, '#' is interpreted + as a regex comment, it is critical to use '\#' instead. + +09/18/06: beazley + Added a @TOKEN decorator function to lex.py that can be used to + define token rules where the documentation string might be computed + in some way. + + digit = r'([0-9])' + nondigit = r'([_A-Za-z])' + identifier = r'(' + nondigit + r'(' + digit + r'|' + nondigit + r')*)' + + from ply.lex import TOKEN + + @TOKEN(identifier) + def t_ID(t): + # Do whatever + + The @TOKEN decorator merely sets the documentation string of the + associated token function as needed for lex to work. + + Note: An alternative solution is the following: + + def t_ID(t): + # Do whatever + + t_ID.__doc__ = identifier + + Note: Decorators require the use of Python 2.4 or later. If compatibility + with old versions is needed, use the latter solution. + + The need for this feature was suggested by Cem Karan. + +09/14/06: beazley + Support for single-character literal tokens has been added to yacc. + These literals must be enclosed in quotes. For example: + + def p_expr(p): + "expr : expr '+' expr" + ... + + def p_expr(p): + 'expr : expr "-" expr' + ... + + In addition to this, it is necessary to tell the lexer module about + literal characters. This is done by defining the variable 'literals' + as a list of characters. This should be defined in the module that + invokes the lex.lex() function. For example: + + literals = ['+','-','*','/','(',')','='] + + or simply + + literals = '+=*/()=' + + It is important to note that literals can only be a single character. + When the lexer fails to match a token using its normal regular expression + rules, it will check the current character against the literal list. + If found, it will be returned with a token type set to match the literal + character. Otherwise, an illegal character will be signalled. + + +09/14/06: beazley + Modified PLY to install itself as a proper Python package called 'ply'. + This will make it a little more friendly to other modules. This + changes the usage of PLY only slightly. Just do this to import the + modules + + import ply.lex as lex + import ply.yacc as yacc + + Alternatively, you can do this: + + from ply import * + + Which imports both the lex and yacc modules. + Change suggested by Lee June. + +09/13/06: beazley + Changed the handling of negative indices when used in production rules. + A negative production index now accesses already parsed symbols on the + parsing stack. For example, + + def p_foo(p): + "foo: A B C D" + print p[1] # Value of 'A' symbol + print p[2] # Value of 'B' symbol + print p[-1] # Value of whatever symbol appears before A + # on the parsing stack. + + p[0] = some_val # Sets the value of the 'foo' grammer symbol + + This behavior makes it easier to work with embedded actions within the + parsing rules. For example, in C-yacc, it is possible to write code like + this: + + bar: A { printf("seen an A = %d\n", $1); } B { do_stuff; } + + In this example, the printf() code executes immediately after A has been + parsed. Within the embedded action code, $1 refers to the A symbol on + the stack. + + To perform this equivalent action in PLY, you need to write a pair + of rules like this: + + def p_bar(p): + "bar : A seen_A B" + do_stuff + + def p_seen_A(p): + "seen_A :" + print "seen an A =", p[-1] + + The second rule "seen_A" is merely a empty production which should be + reduced as soon as A is parsed in the "bar" rule above. The use + of the negative index p[-1] is used to access whatever symbol appeared + before the seen_A symbol. + + This feature also makes it possible to support inherited attributes. + For example: + + def p_decl(p): + "decl : scope name" + + def p_scope(p): + """scope : GLOBAL + | LOCAL""" + p[0] = p[1] + + def p_name(p): + "name : ID" + if p[-1] == "GLOBAL": + # ... + else if p[-1] == "LOCAL": + #... + + In this case, the name rule is inheriting an attribute from the + scope declaration that precedes it. + + *** POTENTIAL INCOMPATIBILITY *** + If you are currently using negative indices within existing grammar rules, + your code will break. This should be extremely rare if non-existent in + most cases. The argument to various grammar rules is not usually not + processed in the same way as a list of items. + +Version 2.0 +------------------------------ +09/07/06: beazley + Major cleanup and refactoring of the LR table generation code. Both SLR + and LALR(1) table generation is now performed by the same code base with + only minor extensions for extra LALR(1) processing. + +09/07/06: beazley + Completely reimplemented the entire LALR(1) parsing engine to use the + DeRemer and Pennello algorithm for calculating lookahead sets. This + significantly improves the performance of generating LALR(1) tables + and has the added feature of actually working correctly! If you + experienced weird behavior with LALR(1) in prior releases, this should + hopefully resolve all of those problems. Many thanks to + Andrew Waters and Markus Schoepflin for submitting bug reports + and helping me test out the revised LALR(1) support. + +Version 1.8 +------------------------------ +08/02/06: beazley + Fixed a problem related to the handling of default actions in LALR(1) + parsing. If you experienced subtle and/or bizarre behavior when trying + to use the LALR(1) engine, this may correct those problems. Patch + contributed by Russ Cox. Note: This patch has been superceded by + revisions for LALR(1) parsing in Ply-2.0. + +08/02/06: beazley + Added support for slicing of productions in yacc. + Patch contributed by Patrick Mezard. + +Version 1.7 +------------------------------ +03/02/06: beazley + Fixed infinite recursion problem ReduceToTerminals() function that + would sometimes come up in LALR(1) table generation. Reported by + Markus Schoepflin. + +03/01/06: beazley + Added "reflags" argument to lex(). For example: + + lex.lex(reflags=re.UNICODE) + + This can be used to specify optional flags to the re.compile() function + used inside the lexer. This may be necessary for special situations such + as processing Unicode (e.g., if you want escapes like \w and \b to consult + the Unicode character property database). The need for this suggested by + Andreas Jung. + +03/01/06: beazley + Fixed a bug with an uninitialized variable on repeated instantiations of parser + objects when the write_tables=0 argument was used. Reported by Michael Brown. + +03/01/06: beazley + Modified lex.py to accept Unicode strings both as the regular expressions for + tokens and as input. Hopefully this is the only change needed for Unicode support. + Patch contributed by Johan Dahl. + +03/01/06: beazley + Modified the class-based interface to work with new-style or old-style classes. + Patch contributed by Michael Brown (although I tweaked it slightly so it would work + with older versions of Python). + +Version 1.6 +------------------------------ +05/27/05: beazley + Incorporated patch contributed by Christopher Stawarz to fix an extremely + devious bug in LALR(1) parser generation. This patch should fix problems + numerous people reported with LALR parsing. + +05/27/05: beazley + Fixed problem with lex.py copy constructor. Reported by Dave Aitel, Aaron Lav, + and Thad Austin. + +05/27/05: beazley + Added outputdir option to yacc() to control output directory. Contributed + by Christopher Stawarz. + +05/27/05: beazley + Added rununit.py test script to run tests using the Python unittest module. + Contributed by Miki Tebeka. + +Version 1.5 +------------------------------ +05/26/04: beazley + Major enhancement. LALR(1) parsing support is now working. + This feature was implemented by Elias Ioup (ezioup@alumni.uchicago.edu) + and optimized by David Beazley. To use LALR(1) parsing do + the following: + + yacc.yacc(method="LALR") + + Computing LALR(1) parsing tables takes about twice as long as + the default SLR method. However, LALR(1) allows you to handle + more complex grammars. For example, the ANSI C grammar + (in example/ansic) has 13 shift-reduce conflicts with SLR, but + only has 1 shift-reduce conflict with LALR(1). + +05/20/04: beazley + Added a __len__ method to parser production lists. Can + be used in parser rules like this: + + def p_somerule(p): + """a : B C D + | E F" + if (len(p) == 3): + # Must have been first rule + elif (len(p) == 2): + # Must be second rule + + Suggested by Joshua Gerth and others. + +Version 1.4 +------------------------------ +04/23/04: beazley + Incorporated a variety of patches contributed by Eric Raymond. + These include: + + 0. Cleans up some comments so they don't wrap on an 80-column display. + 1. Directs compiler errors to stderr where they belong. + 2. Implements and documents automatic line counting when \n is ignored. + 3. Changes the way progress messages are dumped when debugging is on. + The new format is both less verbose and conveys more information than + the old, including shift and reduce actions. + +04/23/04: beazley + Added a Python setup.py file to simply installation. Contributed + by Adam Kerrison. + +04/23/04: beazley + Added patches contributed by Adam Kerrison. + + - Some output is now only shown when debugging is enabled. This + means that PLY will be completely silent when not in debugging mode. + + - An optional parameter "write_tables" can be passed to yacc() to + control whether or not parsing tables are written. By default, + it is true, but it can be turned off if you don't want the yacc + table file. Note: disabling this will cause yacc() to regenerate + the parsing table each time. + +04/23/04: beazley + Added patches contributed by David McNab. This patch addes two + features: + + - The parser can be supplied as a class instead of a module. + For an example of this, see the example/classcalc directory. + + - Debugging output can be directed to a filename of the user's + choice. Use + + yacc(debugfile="somefile.out") + + +Version 1.3 +------------------------------ +12/10/02: jmdyck + Various minor adjustments to the code that Dave checked in today. + Updated test/yacc_{inf,unused}.exp to reflect today's changes. + +12/10/02: beazley + Incorporated a variety of minor bug fixes to empty production + handling and infinite recursion checking. Contributed by + Michael Dyck. + +12/10/02: beazley + Removed bogus recover() method call in yacc.restart() + +Version 1.2 +------------------------------ +11/27/02: beazley + Lexer and parser objects are now available as an attribute + of tokens and slices respectively. For example: + + def t_NUMBER(t): + r'\d+' + print t.lexer + + def p_expr_plus(t): + 'expr: expr PLUS expr' + print t.lexer + print t.parser + + This can be used for state management (if needed). + +10/31/02: beazley + Modified yacc.py to work with Python optimize mode. To make + this work, you need to use + + yacc.yacc(optimize=1) + + Furthermore, you need to first run Python in normal mode + to generate the necessary parsetab.py files. After that, + you can use python -O or python -OO. + + Note: optimized mode turns off a lot of error checking. + Only use when you are sure that your grammar is working. + Make sure parsetab.py is up to date! + +10/30/02: beazley + Added cloning of Lexer objects. For example: + + import copy + l = lex.lex() + lc = copy.copy(l) + + l.input("Some text") + lc.input("Some other text") + ... + + This might be useful if the same "lexer" is meant to + be used in different contexts---or if multiple lexers + are running concurrently. + +10/30/02: beazley + Fixed subtle bug with first set computation and empty productions. + Patch submitted by Michael Dyck. + +10/30/02: beazley + Fixed error messages to use "filename:line: message" instead + of "filename:line. message". This makes error reporting more + friendly to emacs. Patch submitted by François Pinard. + +10/30/02: beazley + Improvements to parser.out file. Terminals and nonterminals + are sorted instead of being printed in random order. + Patch submitted by François Pinard. + +10/30/02: beazley + Improvements to parser.out file output. Rules are now printed + in a way that's easier to understand. Contributed by Russ Cox. + +10/30/02: beazley + Added 'nonassoc' associativity support. This can be used + to disable the chaining of operators like a < b < c. + To use, simply specify 'nonassoc' in the precedence table + + precedence = ( + ('nonassoc', 'LESSTHAN', 'GREATERTHAN'), # Nonassociative operators + ('left', 'PLUS', 'MINUS'), + ('left', 'TIMES', 'DIVIDE'), + ('right', 'UMINUS'), # Unary minus operator + ) + + Patch contributed by Russ Cox. + +10/30/02: beazley + Modified the lexer to provide optional support for Python -O and -OO + modes. To make this work, Python *first* needs to be run in + unoptimized mode. This reads the lexing information and creates a + file "lextab.py". Then, run lex like this: + + # module foo.py + ... + ... + lex.lex(optimize=1) + + Once the lextab file has been created, subsequent calls to + lex.lex() will read data from the lextab file instead of using + introspection. In optimized mode (-O, -OO) everything should + work normally despite the loss of doc strings. + + To change the name of the file 'lextab.py' use the following: + + lex.lex(lextab="footab") + + (this creates a file footab.py) + + +Version 1.1 October 25, 2001 +------------------------------ + +10/25/01: beazley + Modified the table generator to produce much more compact data. + This should greatly reduce the size of the parsetab.py[c] file. + Caveat: the tables still need to be constructed so a little more + work is done in parsetab on import. + +10/25/01: beazley + There may be a possible bug in the cycle detector that reports errors + about infinite recursion. I'm having a little trouble tracking it + down, but if you get this problem, you can disable the cycle + detector as follows: + + yacc.yacc(check_recursion = 0) + +10/25/01: beazley + Fixed a bug in lex.py that sometimes caused illegal characters to be + reported incorrectly. Reported by Sverre Jørgensen. + +7/8/01 : beazley + Added a reference to the underlying lexer object when tokens are handled by + functions. The lexer is available as the 'lexer' attribute. This + was added to provide better lexing support for languages such as Fortran + where certain types of tokens can't be conveniently expressed as regular + expressions (and where the tokenizing function may want to perform a + little backtracking). Suggested by Pearu Peterson. + +6/20/01 : beazley + Modified yacc() function so that an optional starting symbol can be specified. + For example: + + yacc.yacc(start="statement") + + Normally yacc always treats the first production rule as the starting symbol. + However, if you are debugging your grammar it may be useful to specify + an alternative starting symbol. Idea suggested by Rich Salz. + +Version 1.0 June 18, 2001 +-------------------------- +Initial public offering + diff --git a/simulators/gem5/ext/ply/README b/simulators/gem5/ext/ply/README new file mode 100644 index 00000000..d3b785fa --- /dev/null +++ b/simulators/gem5/ext/ply/README @@ -0,0 +1,271 @@ +PLY (Python Lex-Yacc) Version 3.2 + +Copyright (C) 2001-2009, +David M. Beazley (Dabeaz LLC) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the David Beazley or Dabeaz LLC may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Introduction +============ + +PLY is a 100% Python implementation of the common parsing tools lex +and yacc. Here are a few highlights: + + - PLY is very closely modeled after traditional lex/yacc. + If you know how to use these tools in C, you will find PLY + to be similar. + + - PLY provides *very* extensive error reporting and diagnostic + information to assist in parser construction. The original + implementation was developed for instructional purposes. As + a result, the system tries to identify the most common types + of errors made by novice users. + + - PLY provides full support for empty productions, error recovery, + precedence specifiers, and moderately ambiguous grammars. + + - Parsing is based on LR-parsing which is fast, memory efficient, + better suited to large grammars, and which has a number of nice + properties when dealing with syntax errors and other parsing problems. + Currently, PLY builds its parsing tables using the LALR(1) + algorithm used in yacc. + + - PLY uses Python introspection features to build lexers and parsers. + This greatly simplifies the task of parser construction since it reduces + the number of files and eliminates the need to run a separate lex/yacc + tool before running your program. + + - PLY can be used to build parsers for "real" programming languages. + Although it is not ultra-fast due to its Python implementation, + PLY can be used to parse grammars consisting of several hundred + rules (as might be found for a language like C). The lexer and LR + parser are also reasonably efficient when parsing typically + sized programs. People have used PLY to build parsers for + C, C++, ADA, and other real programming languages. + +How to Use +========== + +PLY consists of two files : lex.py and yacc.py. These are contained +within the 'ply' directory which may also be used as a Python package. +To use PLY, simply copy the 'ply' directory to your project and import +lex and yacc from the associated 'ply' package. For example: + + import ply.lex as lex + import ply.yacc as yacc + +Alternatively, you can copy just the files lex.py and yacc.py +individually and use them as modules. For example: + + import lex + import yacc + +The file setup.py can be used to install ply using distutils. + +The file doc/ply.html contains complete documentation on how to use +the system. + +The example directory contains several different examples including a +PLY specification for ANSI C as given in K&R 2nd Ed. + +A simple example is found at the end of this document + +Requirements +============ +PLY requires the use of Python 2.2 or greater. However, you should +use the latest Python release if possible. It should work on just +about any platform. PLY has been tested with both CPython and Jython. +It also seems to work with IronPython. + +Resources +========= +More information about PLY can be obtained on the PLY webpage at: + + http://www.dabeaz.com/ply + +For a detailed overview of parsing theory, consult the excellent +book "Compilers : Principles, Techniques, and Tools" by Aho, Sethi, and +Ullman. The topics found in "Lex & Yacc" by Levine, Mason, and Brown +may also be useful. + +A Google group for PLY can be found at + + http://groups.google.com/group/ply-hack + +Acknowledgments +=============== +A special thanks is in order for all of the students in CS326 who +suffered through about 25 different versions of these tools :-). + +The CHANGES file acknowledges those who have contributed patches. + +Elias Ioup did the first implementation of LALR(1) parsing in PLY-1.x. +Andrew Waters and Markus Schoepflin were instrumental in reporting bugs +and testing a revised LALR(1) implementation for PLY-2.0. + +Special Note for PLY-3.0 +======================== +PLY-3.0 the first PLY release to support Python 3. However, backwards +compatibility with Python 2.2 is still preserved. PLY provides dual +Python 2/3 compatibility by restricting its implementation to a common +subset of basic language features. You should not convert PLY using +2to3--it is not necessary and may in fact break the implementation. + +Example +======= + +Here is a simple example showing a PLY implementation of a calculator +with variables. + +# ----------------------------------------------------------------------------- +# calc.py +# +# A simple calculator with variables. +# ----------------------------------------------------------------------------- + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + t.value = int(t.value) + return t + +# Ignored characters +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print "Illegal character '%s'" % t.value[0] + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex() + +# Precedence rules for the arithmetic operators +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names (for storing variables) +names = { } + +def p_statement_assign(p): + 'statement : NAME EQUALS expression' + names[p[1]] = p[3] + +def p_statement_expr(p): + 'statement : expression' + print p[1] + +def p_expression_binop(p): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + +def p_expression_uminus(p): + 'expression : MINUS expression %prec UMINUS' + p[0] = -p[2] + +def p_expression_group(p): + 'expression : LPAREN expression RPAREN' + p[0] = p[2] + +def p_expression_number(p): + 'expression : NUMBER' + p[0] = p[1] + +def p_expression_name(p): + 'expression : NAME' + try: + p[0] = names[p[1]] + except LookupError: + print "Undefined name '%s'" % p[1] + p[0] = 0 + +def p_error(p): + print "Syntax error at '%s'" % p.value + +import ply.yacc as yacc +yacc.yacc() + +while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + yacc.parse(s) + + +Bug Reports and Patches +======================= +My goal with PLY is to simply have a decent lex/yacc implementation +for Python. As a general rule, I don't spend huge amounts of time +working on it unless I receive very specific bug reports and/or +patches to fix problems. I also try to incorporate submitted feature +requests and enhancements into each new version. To contact me about +bugs and/or new features, please send email to dave@dabeaz.com. + +In addition there is a Google group for discussing PLY related issues at + + http://groups.google.com/group/ply-hack + +-- Dave + + + + + + + + + diff --git a/simulators/gem5/ext/ply/TODO b/simulators/gem5/ext/ply/TODO new file mode 100644 index 00000000..f4800aac --- /dev/null +++ b/simulators/gem5/ext/ply/TODO @@ -0,0 +1,16 @@ +The PLY to-do list: + +1. Finish writing the C Preprocessor module. Started in the + file ply/cpp.py + +2. Create and document libraries of useful tokens. + +3. Expand the examples/yply tool that parses bison/yacc + files. + +4. Think of various diabolical things to do with the + new yacc internals. For example, it is now possible + to specify grammrs using completely different schemes + than the reflection approach used by PLY. + + diff --git a/simulators/gem5/ext/ply/doc/internal.html b/simulators/gem5/ext/ply/doc/internal.html new file mode 100644 index 00000000..3fabfe28 --- /dev/null +++ b/simulators/gem5/ext/ply/doc/internal.html @@ -0,0 +1,874 @@ + + +PLY Internals + + + +

PLY Internals

+ + +David M. Beazley
+dave@dabeaz.com
+
+ +

+PLY Version: 3.0 +

+ + +

+ + + +

1. Introduction

+ + +This document describes classes and functions that make up the internal +operation of PLY. Using this programming interface, it is possible to +manually build an parser using a different interface specification +than what PLY normally uses. For example, you could build a gramar +from information parsed in a completely different input format. Some of +these objects may be useful for building more advanced parsing engines +such as GLR. + +

+It should be stressed that using PLY at this level is not for the +faint of heart. Generally, it's assumed that you know a bit of +the underlying compiler theory and how an LR parser is put together. + +

2. Grammar Class

+ + +The file ply.yacc defines a class Grammar that +is used to hold and manipulate information about a grammar +specification. It encapsulates the same basic information +about a grammar that is put into a YACC file including +the list of tokens, precedence rules, and grammar rules. +Various operations are provided to perform different validations +on the grammar. In addition, there are operations to compute +the first and follow sets that are needed by the various table +generation algorithms. + +

+Grammar(terminals) + +

+Creates a new grammar object. terminals is a list of strings +specifying the terminals for the grammar. An instance g of +Grammar has the following methods: +
+ +

+g.set_precedence(term,assoc,level) +

+Sets the precedence level and associativity for a given terminal term. +assoc is one of 'right', +'left', or 'nonassoc' and level is a positive integer. The higher +the value of level, the higher the precedence. Here is an example of typical +precedence settings: + +
+g.set_precedence('PLUS',  'left',1)
+g.set_precedence('MINUS', 'left',1)
+g.set_precedence('TIMES', 'left',2)
+g.set_precedence('DIVIDE','left',2)
+g.set_precedence('UMINUS','left',3)
+
+ +This method must be called prior to adding any productions to the +grammar with g.add_production(). The precedence of individual grammar +rules is determined by the precedence of the right-most terminal. + +
+

+g.add_production(name,syms,func=None,file='',line=0) +

+Adds a new grammar rule. name is the name of the rule, +syms is a list of symbols making up the right hand +side of the rule, func is the function to call when +reducing the rule. file and line specify +the filename and line number of the rule and are used for +generating error messages. + +

+The list of symbols in syms may include character +literals and %prec specifiers. Here are some +examples: + +

+g.add_production('expr',['expr','PLUS','term'],func,file,line)
+g.add_production('expr',['expr','"+"','term'],func,file,line)
+g.add_production('expr',['MINUS','expr','%prec','UMINUS'],func,file,line)
+
+ +

+If any kind of error is detected, a GrammarError exception +is raised with a message indicating the reason for the failure. +

+ +

+g.set_start(start=None) +

+Sets the starting rule for the grammar. start is a string +specifying the name of the start rule. If start is omitted, +the first grammar rule added with add_production() is taken to be +the starting rule. This method must always be called after all +productions have been added. +
+ +

+g.find_unreachable() +

+Diagnostic function. Returns a list of all unreachable non-terminals +defined in the grammar. This is used to identify inactive parts of +the grammar specification. +
+ +

+g.infinite_cycle() +

+Diagnostic function. Returns a list of all non-terminals in the +grammar that result in an infinite cycle. This condition occurs if +there is no way for a grammar rule to expand to a string containing +only terminal symbols. +
+ +

+g.undefined_symbols() +

+Diagnostic function. Returns a list of tuples (name, prod) +corresponding to undefined symbols in the grammar. name is the +name of the undefined symbol and prod is an instance of +Production which has information about the production rule +where the undefined symbol was used. +
+ +

+g.unused_terminals() +

+Diagnostic function. Returns a list of terminals that were defined, +but never used in the grammar. +
+ +

+g.unused_rules() +

+Diagnostic function. Returns a list of Production instances +corresponding to production rules that were defined in the grammar, +but never used anywhere. This is slightly different +than find_unreachable(). +
+ +

+g.unused_precedence() +

+Diagnostic function. Returns a list of tuples (term, assoc) +corresponding to precedence rules that were set, but never used the +grammar. term is the terminal name and assoc is the +precedence associativity (e.g., 'left', 'right', +or 'nonassoc'. +
+ +

+g.compute_first() +

+Compute all of the first sets for all symbols in the grammar. Returns a dictionary +mapping symbol names to a list of all first symbols. +
+ +

+g.compute_follow() +

+Compute all of the follow sets for all non-terminals in the grammar. +The follow set is the set of all possible symbols that might follow a +given non-terminal. Returns a dictionary mapping non-terminal names +to a list of symbols. +
+ +

+g.build_lritems() +

+Calculates all of the LR items for all productions in the grammar. This +step is required before using the grammar for any kind of table generation. +See the section on LR items below. +
+ +

+The following attributes are set by the above methods and may be useful +in code that works with the grammar. All of these attributes should be +assumed to be read-only. Changing their values directly will likely +break the grammar. + +

+g.Productions +

+A list of all productions added. The first entry is reserved for +a production representing the starting rule. The objects in this list +are instances of the Production class, described shortly. +
+ +

+g.Prodnames +

+A dictionary mapping the names of nonterminals to a list of all +productions of that nonterminal. +
+ +

+g.Terminals +

+A dictionary mapping the names of terminals to a list of the +production numbers where they are used. +
+ +

+g.Nonterminals +

+A dictionary mapping the names of nonterminals to a list of the +production numbers where they are used. +
+ +

+g.First +

+A dictionary representing the first sets for all grammar symbols. This is +computed and returned by the compute_first() method. +
+ +

+g.Follow +

+A dictionary representing the follow sets for all grammar rules. This is +computed and returned by the compute_follow() method. +
+ +

+g.Start +

+Starting symbol for the grammar. Set by the set_start() method. +
+ +For the purposes of debugging, a Grammar object supports the __len__() and +__getitem__() special methods. Accessing g[n] returns the nth production +from the grammar. + + +

3. Productions

+ + +Grammar objects store grammar rules as instances of a Production class. This +class has no public constructor--you should only create productions by calling Grammar.add_production(). +The following attributes are available on a Production instance p. + +

+p.name +

+The name of the production. For a grammar rule such as A : B C D, this is 'A'. +
+ +

+p.prod +

+A tuple of symbols making up the right-hand side of the production. For a grammar rule such as A : B C D, this is ('B','C','D'). +
+ +

+p.number +

+Production number. An integer containing the index of the production in the grammar's Productions list. +
+ +

+p.func +

+The name of the reduction function associated with the production. +This is the function that will execute when reducing the entire +grammar rule during parsing. +
+ +

+p.callable +

+The callable object associated with the name in p.func. This is None +unless the production has been bound using bind(). +
+ +

+p.file +

+Filename associated with the production. Typically this is the file where the production was defined. Used for error messages. +
+ +

+p.lineno +

+Line number associated with the production. Typically this is the line number in p.file where the production was defined. Used for error messages. +
+ +

+p.prec +

+Precedence and associativity associated with the production. This is a tuple (assoc,level) where +assoc is one of 'left','right', or 'nonassoc' and level is +an integer. This value is determined by the precedence of the right-most terminal symbol in the production +or by use of the %prec specifier when adding the production. +
+ +

+p.usyms +

+A list of all unique symbols found in the production. +
+ +

+p.lr_items +

+A list of all LR items for this production. This attribute only has a meaningful value if the +Grammar.build_lritems() method has been called. The items in this list are +instances of LRItem described below. +
+ +

+p.lr_next +

+The head of a linked-list representation of the LR items in p.lr_items. +This attribute only has a meaningful value if the Grammar.build_lritems() +method has been called. Each LRItem instance has a lr_next attribute +to move to the next item. The list is terminated by None. +
+ +

+p.bind(dict) +

+Binds the production function name in p.func to a callable object in +dict. This operation is typically carried out in the last step +prior to running the parsing engine and is needed since parsing tables are typically +read from files which only include the function names, not the functions themselves. +
+ +

+Production objects support +the __len__(), __getitem__(), and __str__() +special methods. +len(p) returns the number of symbols in p.prod +and p[n] is the same as p.prod[n]. + +

4. LRItems

+ + +The construction of parsing tables in an LR-based parser generator is primarily +done over a set of "LR Items". An LR item represents a stage of parsing one +of the grammar rules. To compute the LR items, it is first necessary to +call Grammar.build_lritems(). Once this step, all of the productions +in the grammar will have their LR items attached to them. + +

+Here is an interactive example that shows what LR items look like if you +interactively experiment. In this example, g is a Grammar +object. + +

+
+>>> g.build_lritems()
+>>> p = g[1]
+>>> p
+Production(statement -> ID = expr)
+>>>
+
+
+ +In the above code, p represents the first grammar rule. In +this case, a rule 'statement -> ID = expr'. + +

+Now, let's look at the LR items for p. + +

+
+>>> p.lr_items
+[LRItem(statement -> . ID = expr), 
+ LRItem(statement -> ID . = expr), 
+ LRItem(statement -> ID = . expr), 
+ LRItem(statement -> ID = expr .)]
+>>>
+
+
+ +In each LR item, the dot (.) represents a specific stage of parsing. In each LR item, the dot +is advanced by one symbol. It is only when the dot reaches the very end that a production +is successfully parsed. + +

+An instance lr of LRItem has the following +attributes that hold information related to that specific stage of +parsing. + +

+lr.name +

+The name of the grammar rule. For example, 'statement' in the above example. +
+ +

+lr.prod +

+A tuple of symbols representing the right-hand side of the production, including the +special '.' character. For example, ('ID','.','=','expr'). +
+ +

+lr.number +

+An integer representing the production number in the grammar. +
+ +

+lr.usyms +

+A set of unique symbols in the production. Inherited from the original Production instance. +
+ +

+lr.lr_index +

+An integer representing the position of the dot (.). You should never use lr.prod.index() +to search for it--the result will be wrong if the grammar happens to also use (.) as a character +literal. +
+ +

+lr.lr_after +

+A list of all productions that can legally appear immediately to the right of the +dot (.). This list contains Production instances. This attribute +represents all of the possible branches a parse can take from the current position. +For example, suppose that lr represents a stage immediately before +an expression like this: + +
+>>> lr
+LRItem(statement -> ID = . expr)
+>>>
+
+ +Then, the value of lr.lr_after might look like this, showing all productions that +can legally appear next: + +
+>>> lr.lr_after
+[Production(expr -> expr PLUS expr), 
+ Production(expr -> expr MINUS expr), 
+ Production(expr -> expr TIMES expr), 
+ Production(expr -> expr DIVIDE expr), 
+ Production(expr -> MINUS expr), 
+ Production(expr -> LPAREN expr RPAREN), 
+ Production(expr -> NUMBER), 
+ Production(expr -> ID)]
+>>>
+
+ +
+ +

+lr.lr_before +

+The grammar symbol that appears immediately before the dot (.) or None if +at the beginning of the parse. +
+ +

+lr.lr_next +

+A link to the next LR item, representing the next stage of the parse. None if lr +is the last LR item. +
+ +LRItem instances also support the __len__() and __getitem__() special methods. +len(lr) returns the number of items in lr.prod including the dot (.). lr[n] +returns lr.prod[n]. + +

+It goes without saying that all of the attributes associated with LR +items should be assumed to be read-only. Modifications will very +likely create a small black-hole that will consume you and your code. + +

5. LRTable

+ + +The LRTable class is used to represent LR parsing table data. This +minimally includes the production list, action table, and goto table. + +

+LRTable() +

+Create an empty LRTable object. This object contains only the information needed to +run an LR parser. +
+ +An instance lrtab of LRTable has the following methods: + +

+lrtab.read_table(module) +

+Populates the LR table with information from the module specified in module. +module is either a module object already loaded with import or +the name of a Python module. If it's a string containing a module name, it is +loaded and parsing data is extracted. Returns the signature value that was used +when initially writing the tables. Raises a VersionError exception if +the module was created using an incompatible version of PLY. +
+ +

+lrtab.bind_callables(dict) +

+This binds all of the function names used in productions to callable objects +found in the dictionary dict. During table generation and when reading +LR tables from files, PLY only uses the names of action functions such as 'p_expr', +'p_statement', etc. In order to actually run the parser, these names +have to be bound to callable objects. This method is always called prior to +running a parser. +
+ +After lrtab has been populated, the following attributes are defined. + +

+lrtab.lr_method +

+The LR parsing method used (e.g., 'LALR') +
+ + +

+lrtab.lr_productions +

+The production list. If the parsing tables have been newly +constructed, this will be a list of Production instances. If +the parsing tables have been read from a file, it's a list +of MiniProduction instances. This, together +with lr_action and lr_goto contain all of the +information needed by the LR parsing engine. +
+ +

+lrtab.lr_action +

+The LR action dictionary that implements the underlying state machine. +The keys of this dictionary are the LR states. +
+ +

+lrtab.lr_goto +

+The LR goto table that contains information about grammar rule reductions. +
+ + +

6. LRGeneratedTable

+ + +The LRGeneratedTable class represents constructed LR parsing tables on a +grammar. It is a subclass of LRTable. + +

+LRGeneratedTable(grammar, method='LALR',log=None) +

+Create the LR parsing tables on a grammar. grammar is an instance of Grammar, +method is a string with the parsing method ('SLR' or 'LALR'), and +log is a logger object used to write debugging information. The debugging information +written to log is the same as what appears in the parser.out file created +by yacc. By supplying a custom logger with a different message format, it is possible to get +more information (e.g., the line number in yacc.py used for issuing each line of +output in the log). The result is an instance of LRGeneratedTable. +
+ +

+An instance lr of LRGeneratedTable has the following attributes. + +

+lr.grammar +

+A link to the Grammar object used to construct the parsing tables. +
+ +

+lr.lr_method +

+The LR parsing method used (e.g., 'LALR') +
+ + +

+lr.lr_productions +

+A reference to grammar.Productions. This, together with lr_action and lr_goto +contain all of the information needed by the LR parsing engine. +
+ +

+lr.lr_action +

+The LR action dictionary that implements the underlying state machine. The keys of this dictionary are +the LR states. +
+ +

+lr.lr_goto +

+The LR goto table that contains information about grammar rule reductions. +
+ +

+lr.sr_conflicts +

+A list of tuples (state,token,resolution) identifying all shift/reduce conflicts. state is the LR state +number where the conflict occurred, token is the token causing the conflict, and resolution is +a string describing the resolution taken. resolution is either 'shift' or 'reduce'. +
+ +

+lr.rr_conflicts +

+A list of tuples (state,rule,rejected) identifying all reduce/reduce conflicts. state is the +LR state number where the conflict occurred, rule is the production rule that was selected +and rejected is the production rule that was rejected. Both rule and rejected are +instances of Production. They can be inspected to provide the user with more information. +
+ +

+There are two public methods of LRGeneratedTable. + +

+lr.write_table(modulename,outputdir="",signature="") +

+Writes the LR parsing table information to a Python module. modulename is a string +specifying the name of a module such as "parsetab". outputdir is the name of a +directory where the module should be created. signature is a string representing a +grammar signature that's written into the output file. This can be used to detect when +the data stored in a module file is out-of-sync with the the grammar specification (and that +the tables need to be regenerated). If modulename is a string "parsetab", +this function creates a file called parsetab.py. If the module name represents a +package such as "foo.bar.parsetab", then only the last component, "parsetab" is +used. +
+ + +

7. LRParser

+ + +The LRParser class implements the low-level LR parsing engine. + + +

+LRParser(lrtab, error_func) +

+Create an LRParser. lrtab is an instance of LRTable +containing the LR production and state tables. error_func is the +error function to invoke in the event of a parsing error. +
+ +An instance p of LRParser has the following methods: + +

+p.parse(input=None,lexer=None,debug=0,tracking=0,tokenfunc=None) +

+Run the parser. input is a string, which if supplied is fed into the +lexer using its input() method. lexer is an instance of the +Lexer class to use for tokenizing. If not supplied, the last lexer +created with the lex module is used. debug is a boolean flag +that enables debugging. tracking is a boolean flag that tells the +parser to perform additional line number tracking. tokenfunc is a callable +function that returns the next token. If supplied, the parser will use it to get +all tokens. +
+ +

+p.restart() +

+Resets the parser state for a parse already in progress. +
+ +

8. ParserReflect

+ + +

+The ParserReflect class is used to collect parser specification data +from a Python module or object. This class is what collects all of the +p_rule() functions in a PLY file, performs basic error checking, +and collects all of the needed information to build a grammar. Most of the +high-level PLY interface as used by the yacc() function is actually +implemented by this class. + +

+ParserReflect(pdict, log=None) +

+Creates a ParserReflect instance. pdict is a dictionary +containing parser specification data. This dictionary typically corresponds +to the module or class dictionary of code that implements a PLY parser. +log is a logger instance that will be used to report error +messages. +
+ +An instance p of ParserReflect has the following methods: + +

+p.get_all() +

+Collect and store all required parsing information. +
+ +

+p.validate_all() +

+Validate all of the collected parsing information. This is a seprate step +from p.get_all() as a performance optimization. In order to +increase parser start-up time, a parser can elect to only validate the +parsing data when regenerating the parsing tables. The validation +step tries to collect as much information as possible rather than +raising an exception at the first sign of trouble. The attribute +p.error is set if there are any validation errors. The +value of this attribute is also returned. +
+ +

+p.signature() +

+Compute a signature representing the contents of the collected parsing +data. The signature value should change if anything in the parser +specification has changed in a way that would justify parser table +regeneration. This method can be called after p.get_all(), +but before p.validate_all(). +
+ +The following attributes are set in the process of collecting data: + +

+p.start +

+The grammar start symbol, if any. Taken from pdict['start']. +
+ +

+p.error_func +

+The error handling function or None. Taken from pdict['p_error']. +
+ +

+p.tokens +

+The token list. Taken from pdict['tokens']. +
+ +

+p.prec +

+The precedence specifier. Taken from pdict['precedence']. +
+ +

+p.preclist +

+A parsed version of the precedence specified. A list of tuples of the form +(token,assoc,level) where token is the terminal symbol, +assoc is the associativity (e.g., 'left') and level +is a numeric precedence level. +
+ +

+p.grammar +

+A list of tuples (name, rules) representing the grammar rules. name is the +name of a Python function or method in pdict that starts with "p_". +rules is a list of tuples (filename,line,prodname,syms) representing +the grammar rules found in the documentation string of that function. filename and line contain location +information that can be used for debugging. prodname is the name of the +production. syms is the right-hand side of the production. If you have a +function like this + +
+def p_expr(p):
+    '''expr : expr PLUS expr
+            | expr MINUS expr
+            | expr TIMES expr
+            | expr DIVIDE expr'''
+
+ +then the corresponding entry in p.grammar might look like this: + +
+('p_expr', [ ('calc.py',10,'expr', ['expr','PLUS','expr']),
+             ('calc.py',11,'expr', ['expr','MINUS','expr']),
+             ('calc.py',12,'expr', ['expr','TIMES','expr']),
+             ('calc.py',13,'expr', ['expr','DIVIDE','expr'])
+           ])
+
+
+ +

+p.pfuncs +

+A sorted list of tuples (line, file, name, doc) representing all of +the p_ functions found. line and file give location +information. name is the name of the function. doc is the +documentation string. This list is sorted in ascending order by line number. +
+ +

+p.files +

+A dictionary holding all of the source filenames that were encountered +while collecting parser information. Only the keys of this dictionary have +any meaning. +
+ +

+p.error +

+An attribute that indicates whether or not any critical errors +occurred in validation. If this is set, it means that that some kind +of problem was detected and that no further processing should be +performed. +
+ + +

9. High-level operation

+ + +Using all of the above classes requires some attention to detail. The yacc() +function carries out a very specific sequence of operations to create a grammar. +This same sequence should be emulated if you build an alternative PLY interface. + +
    +
  1. A ParserReflect object is created and raw grammar specification data is +collected. +
  2. A Grammar object is created and populated with information +from the specification data. +
  3. A LRGenerator object is created to run the LALR algorithm over +the Grammar object. +
  4. Productions in the LRGenerator and bound to callables using the bind_callables() +method. +
  5. A LRParser object is created from from the information in the +LRGenerator object. +
+ + + + + + + + + + diff --git a/simulators/gem5/ext/ply/doc/makedoc.py b/simulators/gem5/ext/ply/doc/makedoc.py new file mode 100644 index 00000000..415a53aa --- /dev/null +++ b/simulators/gem5/ext/ply/doc/makedoc.py @@ -0,0 +1,194 @@ +#!/usr/local/bin/python + +############################################################################### +# Takes a chapter as input and adds internal links and numbering to all +# of the H1, H2, H3, H4 and H5 sections. +# +# Every heading HTML tag (H1, H2 etc) is given an autogenerated name to link +# to. However, if the name is not an autogenerated name from a previous run, +# it will be kept. If it is autogenerated, it might change on subsequent runs +# of this program. Thus if you want to create links to one of the headings, +# then change the heading link name to something that does not look like an +# autogenerated link name. +############################################################################### + +import sys +import re +import string + +############################################################################### +# Functions +############################################################################### + +# Regexs for +alink = re.compile(r"", re.IGNORECASE) +heading = re.compile(r"(_nn\d)", re.IGNORECASE) + +def getheadingname(m): + autogeneratedheading = True; + if m.group(1) != None: + amatch = alink.match(m.group(1)) + if amatch: + # A non-autogenerated heading - keep it + headingname = amatch.group(1) + autogeneratedheading = heading.match(headingname) + if autogeneratedheading: + # The heading name was either non-existent or autogenerated, + # We can create a new heading / change the existing heading + headingname = "%s_nn%d" % (filenamebase, nameindex) + return headingname + +############################################################################### +# Main program +############################################################################### + +if len(sys.argv) != 2: + print "usage: makedoc.py filename" + sys.exit(1) + +filename = sys.argv[1] +filenamebase = string.split(filename,".")[0] + +section = 0 +subsection = 0 +subsubsection = 0 +subsubsubsection = 0 +nameindex = 0 + +name = "" + +# Regexs for

,...

sections + +h1 = re.compile(r".*?

()*[\d\.\s]*(.*?)

", re.IGNORECASE) +h2 = re.compile(r".*?

()*[\d\.\s]*(.*?)

", re.IGNORECASE) +h3 = re.compile(r".*?

()*[\d\.\s]*(.*?)

", re.IGNORECASE) +h4 = re.compile(r".*?

()*[\d\.\s]*(.*?)

", re.IGNORECASE) +h5 = re.compile(r".*?
()*[\d\.\s]*(.*?)
", re.IGNORECASE) + +data = open(filename).read() # Read data +open(filename+".bak","w").write(data) # Make backup + +lines = data.splitlines() +result = [ ] # This is the result of postprocessing the file +index = "\n
\n" # index contains the index for adding at the top of the file. Also printed to stdout. + +skip = 0 +skipspace = 0 + +for s in lines: + if s == "": + if not skip: + result.append("@INDEX@") + skip = 1 + else: + skip = 0 + continue; + if skip: + continue + + if not s and skipspace: + continue + + if skipspace: + result.append("") + result.append("") + skipspace = 0 + + m = h2.match(s) + if m: + prevheadingtext = m.group(2) + nameindex += 1 + section += 1 + headingname = getheadingname(m) + result.append("""

%d. %s

""" % (headingname,section, prevheadingtext)) + + if subsubsubsection: + index += "\n" + if subsubsection: + index += "\n" + if subsection: + index += "\n" + if section == 1: + index += "
    \n" + + index += """
  • %s\n""" % (headingname,prevheadingtext) + subsection = 0 + subsubsection = 0 + subsubsubsection = 0 + skipspace = 1 + continue + m = h3.match(s) + if m: + prevheadingtext = m.group(2) + nameindex += 1 + subsection += 1 + headingname = getheadingname(m) + result.append("""

    %d.%d %s

    """ % (headingname,section, subsection, prevheadingtext)) + + if subsubsubsection: + index += "
\n" + if subsubsection: + index += "\n" + if subsection == 1: + index += "
    \n" + + index += """
  • %s\n""" % (headingname,prevheadingtext) + subsubsection = 0 + skipspace = 1 + continue + m = h4.match(s) + if m: + prevheadingtext = m.group(2) + nameindex += 1 + subsubsection += 1 + subsubsubsection = 0 + headingname = getheadingname(m) + result.append("""

    %d.%d.%d %s

    """ % (headingname,section, subsection, subsubsection, prevheadingtext)) + + if subsubsubsection: + index += "
\n" + if subsubsection == 1: + index += "
    \n" + + index += """
  • %s\n""" % (headingname,prevheadingtext) + skipspace = 1 + continue + m = h5.match(s) + if m: + prevheadingtext = m.group(2) + nameindex += 1 + subsubsubsection += 1 + headingname = getheadingname(m) + result.append("""
    %d.%d.%d.%d %s
    """ % (headingname,section, subsection, subsubsection, subsubsubsection, prevheadingtext)) + + if subsubsubsection == 1: + index += "
      \n" + + index += """
    • %s\n""" % (headingname,prevheadingtext) + skipspace = 1 + continue + + result.append(s) + +if subsubsubsection: + index += "
    \n" + +if subsubsection: + index += "
\n" + +if subsection: + index += "\n" + +if section: + index += "\n" + +index += "
\n\n" + +data = "\n".join(result) + +data = data.replace("@INDEX@",index) + "\n"; + +# Write the file back out +open(filename,"w").write(data) + + diff --git a/simulators/gem5/ext/ply/doc/ply.html b/simulators/gem5/ext/ply/doc/ply.html new file mode 100644 index 00000000..3345e792 --- /dev/null +++ b/simulators/gem5/ext/ply/doc/ply.html @@ -0,0 +1,3261 @@ + + +PLY (Python Lex-Yacc) + + + +

PLY (Python Lex-Yacc)

+ + +David M. Beazley
+dave@dabeaz.com
+
+ +

+PLY Version: 3.0 +

+ + +

+ + + + +

1. Preface and Requirements

+ + +

+This document provides an overview of lexing and parsing with PLY. +Given the intrinsic complexity of parsing, I would strongly advise +that you read (or at least skim) this entire document before jumping +into a big development project with PLY. +

+ +

+PLY-3.0 is compatible with both Python 2 and Python 3. Be aware that +Python 3 support is new and has not been extensively tested (although +all of the examples and unit tests pass under Python 3.0). If you are +using Python 2, you should try to use Python 2.4 or newer. Although PLY +works with versions as far back as Python 2.2, some of its optional features +require more modern library modules. +

+ +

2. Introduction

+ + +PLY is a pure-Python implementation of the popular compiler +construction tools lex and yacc. The main goal of PLY is to stay +fairly faithful to the way in which traditional lex/yacc tools work. +This includes supporting LALR(1) parsing as well as providing +extensive input validation, error reporting, and diagnostics. Thus, +if you've used yacc in another programming language, it should be +relatively straightforward to use PLY. + +

+Early versions of PLY were developed to support an Introduction to +Compilers Course I taught in 2001 at the University of Chicago. In this course, +students built a fully functional compiler for a simple Pascal-like +language. Their compiler, implemented entirely in Python, had to +include lexical analysis, parsing, type checking, type inference, +nested scoping, and code generation for the SPARC processor. +Approximately 30 different compiler implementations were completed in +this course. Most of PLY's interface and operation has been influenced by common +usability problems encountered by students. Since 2001, PLY has +continued to be improved as feedback has been received from users. +PLY-3.0 represents a major refactoring of the original implementation +with an eye towards future enhancements. + +

+Since PLY was primarily developed as an instructional tool, you will +find it to be fairly picky about token and grammar rule +specification. In part, this +added formality is meant to catch common programming mistakes made by +novice users. However, advanced users will also find such features to +be useful when building complicated grammars for real programming +languages. It should also be noted that PLY does not provide much in +the way of bells and whistles (e.g., automatic construction of +abstract syntax trees, tree traversal, etc.). Nor would I consider it +to be a parsing framework. Instead, you will find a bare-bones, yet +fully capable lex/yacc implementation written entirely in Python. + +

+The rest of this document assumes that you are somewhat familar with +parsing theory, syntax directed translation, and the use of compiler +construction tools such as lex and yacc in other programming +languages. If you are unfamilar with these topics, you will probably +want to consult an introductory text such as "Compilers: Principles, +Techniques, and Tools", by Aho, Sethi, and Ullman. O'Reilly's "Lex +and Yacc" by John Levine may also be handy. In fact, the O'Reilly book can be +used as a reference for PLY as the concepts are virtually identical. + +

3. PLY Overview

+ + +PLY consists of two separate modules; lex.py and +yacc.py, both of which are found in a Python package +called ply. The lex.py module is used to break input text into a +collection of tokens specified by a collection of regular expression +rules. yacc.py is used to recognize language syntax that has +been specified in the form of a context free grammar. yacc.py uses LR parsing and generates its parsing tables +using either the LALR(1) (the default) or SLR table generation algorithms. + +

+The two tools are meant to work together. Specifically, +lex.py provides an external interface in the form of a +token() function that returns the next valid token on the +input stream. yacc.py calls this repeatedly to retrieve +tokens and invoke grammar rules. The output of yacc.py is +often an Abstract Syntax Tree (AST). However, this is entirely up to +the user. If desired, yacc.py can also be used to implement +simple one-pass compilers. + +

+Like its Unix counterpart, yacc.py provides most of the +features you expect including extensive error checking, grammar +validation, support for empty productions, error tokens, and ambiguity +resolution via precedence rules. In fact, everything that is possible in traditional yacc +should be supported in PLY. + +

+The primary difference between +yacc.py and Unix yacc is that yacc.py +doesn't involve a separate code-generation process. +Instead, PLY relies on reflection (introspection) +to build its lexers and parsers. Unlike traditional lex/yacc which +require a special input file that is converted into a separate source +file, the specifications given to PLY are valid Python +programs. This means that there are no extra source files nor is +there a special compiler construction step (e.g., running yacc to +generate Python code for the compiler). Since the generation of the +parsing tables is relatively expensive, PLY caches the results and +saves them to a file. If no changes are detected in the input source, +the tables are read from the cache. Otherwise, they are regenerated. + +

4. Lex

+ + +lex.py is used to tokenize an input string. For example, suppose +you're writing a programming language and a user supplied the following input string: + +
+
+x = 3 + 42 * (s - t)
+
+
+ +A tokenizer splits the string into individual tokens + +
+
+'x','=', '3', '+', '42', '*', '(', 's', '-', 't', ')'
+
+
+ +Tokens are usually given names to indicate what they are. For example: + +
+
+'ID','EQUALS','NUMBER','PLUS','NUMBER','TIMES',
+'LPAREN','ID','MINUS','ID','RPAREN'
+
+
+ +More specifically, the input is broken into pairs of token types and values. For example: + +
+
+('ID','x'), ('EQUALS','='), ('NUMBER','3'), 
+('PLUS','+'), ('NUMBER','42), ('TIMES','*'),
+('LPAREN','('), ('ID','s'), ('MINUS','-'),
+('ID','t'), ('RPAREN',')'
+
+
+ +The identification of tokens is typically done by writing a series of regular expression +rules. The next section shows how this is done using lex.py. + +

4.1 Lex Example

+ + +The following example shows how lex.py is used to write a simple tokenizer. + +
+
+# ------------------------------------------------------------
+# calclex.py
+#
+# tokenizer for a simple expression evaluator for
+# numbers and +,-,*,/
+# ------------------------------------------------------------
+import ply.lex as lex
+
+# List of token names.   This is always required
+tokens = (
+   'NUMBER',
+   'PLUS',
+   'MINUS',
+   'TIMES',
+   'DIVIDE',
+   'LPAREN',
+   'RPAREN',
+)
+
+# Regular expression rules for simple tokens
+t_PLUS    = r'\+'
+t_MINUS   = r'-'
+t_TIMES   = r'\*'
+t_DIVIDE  = r'/'
+t_LPAREN  = r'\('
+t_RPAREN  = r'\)'
+
+# A regular expression rule with some action code
+def t_NUMBER(t):
+    r'\d+'
+    t.value = int(t.value)    
+    return t
+
+# Define a rule so we can track line numbers
+def t_newline(t):
+    r'\n+'
+    t.lexer.lineno += len(t.value)
+
+# A string containing ignored characters (spaces and tabs)
+t_ignore  = ' \t'
+
+# Error handling rule
+def t_error(t):
+    print "Illegal character '%s'" % t.value[0]
+    t.lexer.skip(1)
+
+# Build the lexer
+lexer = lex.lex()
+
+
+
+To use the lexer, you first need to feed it some input text using +its input() method. After that, repeated calls +to token() produce tokens. The following code shows how this +works: + +
+
+
+# Test it out
+data = '''
+3 + 4 * 10
+  + -20 *2
+'''
+
+# Give the lexer some input
+lexer.input(data)
+
+# Tokenize
+while True:
+    tok = lexer.token()
+    if not tok: break      # No more input
+    print tok
+
+
+ +When executed, the example will produce the following output: + +
+
+$ python example.py
+LexToken(NUMBER,3,2,1)
+LexToken(PLUS,'+',2,3)
+LexToken(NUMBER,4,2,5)
+LexToken(TIMES,'*',2,7)
+LexToken(NUMBER,10,2,10)
+LexToken(PLUS,'+',3,14)
+LexToken(MINUS,'-',3,16)
+LexToken(NUMBER,20,3,18)
+LexToken(TIMES,'*',3,20)
+LexToken(NUMBER,2,3,21)
+
+
+ +Lexers also support the iteration protocol. So, you can write the above loop as follows: + +
+
+for tok in lexer:
+    print tok
+
+
+ +The tokens returned by lexer.token() are instances +of LexToken. This object has +attributes tok.type, tok.value, +tok.lineno, and tok.lexpos. The following code shows an example of +accessing these attributes: + +
+
+# Tokenize
+while True:
+    tok = lexer.token()
+    if not tok: break      # No more input
+    print tok.type, tok.value, tok.line, tok.lexpos
+
+
+ +The tok.type and tok.value attributes contain the +type and value of the token itself. +tok.line and tok.lexpos contain information about +the location of the token. tok.lexpos is the index of the +token relative to the start of the input text. + +

4.2 The tokens list

+ + +All lexers must provide a list tokens that defines all of the possible token +names that can be produced by the lexer. This list is always required +and is used to perform a variety of validation checks. The tokens list is also used by the +yacc.py module to identify terminals. + +

+In the example, the following code specified the token names: + +

+
+tokens = (
+   'NUMBER',
+   'PLUS',
+   'MINUS',
+   'TIMES',
+   'DIVIDE',
+   'LPAREN',
+   'RPAREN',
+)
+
+
+ +

4.3 Specification of tokens

+ + +Each token is specified by writing a regular expression rule. Each of these rules are +are defined by making declarations with a special prefix t_ to indicate that it +defines a token. For simple tokens, the regular expression can +be specified as strings such as this (note: Python raw strings are used since they are the +most convenient way to write regular expression strings): + +
+
+t_PLUS = r'\+'
+
+
+ +In this case, the name following the t_ must exactly match one of the +names supplied in tokens. If some kind of action needs to be performed, +a token rule can be specified as a function. For example, this rule matches numbers and +converts the string into a Python integer. + +
+
+def t_NUMBER(t):
+    r'\d+'
+    t.value = int(t.value)
+    return t
+
+
+ +When a function is used, the regular expression rule is specified in the function documentation string. +The function always takes a single argument which is an instance of +LexToken. This object has attributes of t.type which is the token type (as a string), +t.value which is the lexeme (the actual text matched), t.lineno which is the current line number, and t.lexpos which +is the position of the token relative to the beginning of the input text. +By default, t.type is set to the name following the t_ prefix. The action +function can modify the contents of the LexToken object as appropriate. However, +when it is done, the resulting token should be returned. If no value is returned by the action +function, the token is simply discarded and the next token read. + +

+Internally, lex.py uses the re module to do its patten matching. When building the master regular expression, +rules are added in the following order: +

+

    +
  1. All tokens defined by functions are added in the same order as they appear in the lexer file. +
  2. Tokens defined by strings are added next by sorting them in order of decreasing regular expression length (longer expressions +are added first). +
+

+Without this ordering, it can be difficult to correctly match certain types of tokens. For example, if you +wanted to have separate tokens for "=" and "==", you need to make sure that "==" is checked first. By sorting regular +expressions in order of decreasing length, this problem is solved for rules defined as strings. For functions, +the order can be explicitly controlled since rules appearing first are checked first. + +

+To handle reserved words, you should write a single rule to match an +identifier and do a special name lookup in a function like this: + +

+
+reserved = {
+   'if' : 'IF',
+   'then' : 'THEN',
+   'else' : 'ELSE',
+   'while' : 'WHILE',
+   ...
+}
+
+tokens = ['LPAREN','RPAREN',...,'ID'] + list(reserved.values())
+
+def t_ID(t):
+    r'[a-zA-Z_][a-zA-Z_0-9]*'
+    t.type = reserved.get(t.value,'ID')    # Check for reserved words
+    return t
+
+
+ +This approach greatly reduces the number of regular expression rules and is likely to make things a little faster. + +

+Note: You should avoid writing individual rules for reserved words. For example, if you write rules like this, + +

+
+t_FOR   = r'for'
+t_PRINT = r'print'
+
+
+ +those rules will be triggered for identifiers that include those words as a prefix such as "forget" or "printed". This is probably not +what you want. + +

4.4 Token values

+ + +When tokens are returned by lex, they have a value that is stored in the value attribute. Normally, the value is the text +that was matched. However, the value can be assigned to any Python object. For instance, when lexing identifiers, you may +want to return both the identifier name and information from some sort of symbol table. To do this, you might write a rule like this: + +
+
+def t_ID(t):
+    ...
+    # Look up symbol table information and return a tuple
+    t.value = (t.value, symbol_lookup(t.value))
+    ...
+    return t
+
+
+ +It is important to note that storing data in other attribute names is not recommended. The yacc.py module only exposes the +contents of the value attribute. Thus, accessing other attributes may be unnecessarily awkward. If you +need to store multiple values on a token, assign a tuple, dictionary, or instance to value. + +

4.5 Discarded tokens

+ + +To discard a token, such as a comment, simply define a token rule that returns no value. For example: + +
+
+def t_COMMENT(t):
+    r'\#.*'
+    pass
+    # No return value. Token discarded
+
+
+ +Alternatively, you can include the prefix "ignore_" in the token declaration to force a token to be ignored. For example: + +
+
+t_ignore_COMMENT = r'\#.*'
+
+
+ +Be advised that if you are ignoring many different kinds of text, you may still want to use functions since these provide more precise +control over the order in which regular expressions are matched (i.e., functions are matched in order of specification whereas strings are +sorted by regular expression length). + +

4.6 Line numbers and positional information

+ + +

By default, lex.py knows nothing about line numbers. This is because lex.py doesn't know anything +about what constitutes a "line" of input (e.g., the newline character or even if the input is textual data). +To update this information, you need to write a special rule. In the example, the t_newline() rule shows how to do this. + +

+
+# Define a rule so we can track line numbers
+def t_newline(t):
+    r'\n+'
+    t.lexer.lineno += len(t.value)
+
+
+Within the rule, the lineno attribute of the underlying lexer t.lexer is updated. +After the line number is updated, the token is simply discarded since nothing is returned. + +

+lex.py does not perform and kind of automatic column tracking. However, it does record positional +information related to each token in the lexpos attribute. Using this, it is usually possible to compute +column information as a separate step. For instance, just count backwards until you reach a newline. + +

+
+# Compute column. 
+#     input is the input text string
+#     token is a token instance
+def find_column(input,token):
+    last_cr = input.rfind('\n',0,token.lexpos)
+    if last_cr < 0:
+	last_cr = 0
+    column = (token.lexpos - last_cr) + 1
+    return column
+
+
+ +Since column information is often only useful in the context of error handling, calculating the column +position can be performed when needed as opposed to doing it for each token. + +

4.7 Ignored characters

+ + +

+The special t_ignore rule is reserved by lex.py for characters +that should be completely ignored in the input stream. +Usually this is used to skip over whitespace and other non-essential characters. +Although it is possible to define a regular expression rule for whitespace in a manner +similar to t_newline(), the use of t_ignore provides substantially better +lexing performance because it is handled as a special case and is checked in a much +more efficient manner than the normal regular expression rules. + +

4.8 Literal characters

+ + +

+Literal characters can be specified by defining a variable literals in your lexing module. For example: + +

+
+literals = [ '+','-','*','/' ]
+
+
+ +or alternatively + +
+
+literals = "+-*/"
+
+
+ +A literal character is simply a single character that is returned "as is" when encountered by the lexer. Literals are checked +after all of the defined regular expression rules. Thus, if a rule starts with one of the literal characters, it will always +take precedence. +

+When a literal token is returned, both its type and value attributes are set to the character itself. For example, '+'. + +

4.9 Error handling

+ + +

+Finally, the t_error() +function is used to handle lexing errors that occur when illegal +characters are detected. In this case, the t.value attribute contains the +rest of the input string that has not been tokenized. In the example, the error function +was defined as follows: + +

+
+# Error handling rule
+def t_error(t):
+    print "Illegal character '%s'" % t.value[0]
+    t.lexer.skip(1)
+
+
+ +In this case, we simply print the offending character and skip ahead one character by calling t.lexer.skip(1). + +

4.10 Building and using the lexer

+ + +

+To build the lexer, the function lex.lex() is used. This function +uses Python reflection (or introspection) to read the the regular expression rules +out of the calling context and build the lexer. Once the lexer has been built, two methods can +be used to control the lexer. + +

    +
  • lexer.input(data). Reset the lexer and store a new input string. +
  • lexer.token(). Return the next token. Returns a special LexToken instance on success or +None if the end of the input text has been reached. +
+ +The preferred way to use PLY is to invoke the above methods directly on the lexer object returned by the +lex() function. The legacy interface to PLY involves module-level functions lex.input() and lex.token(). +For example: + +
+
+lex.lex()
+lex.input(sometext)
+while 1:
+    tok = lex.token()
+    if not tok: break
+    print tok
+
+
+ +

+In this example, the module-level functions lex.input() and lex.token() are bound to the input() +and token() methods of the last lexer created by the lex module. This interface may go away at some point so +it's probably best not to use it. + +

4.11 The @TOKEN decorator

+ + +In some applications, you may want to define build tokens from as a series of +more complex regular expression rules. For example: + +
+
+digit            = r'([0-9])'
+nondigit         = r'([_A-Za-z])'
+identifier       = r'(' + nondigit + r'(' + digit + r'|' + nondigit + r')*)'        
+
+def t_ID(t):
+    # want docstring to be identifier above. ?????
+    ...
+
+
+ +In this case, we want the regular expression rule for ID to be one of the variables above. However, there is no +way to directly specify this using a normal documentation string. To solve this problem, you can use the @TOKEN +decorator. For example: + +
+
+from ply.lex import TOKEN
+
+@TOKEN(identifier)
+def t_ID(t):
+    ...
+
+
+ +This will attach identifier to the docstring for t_ID() allowing lex.py to work normally. An alternative +approach this problem is to set the docstring directly like this: + +
+
+def t_ID(t):
+    ...
+
+t_ID.__doc__ = identifier
+
+
+ +NOTE: Use of @TOKEN requires Python-2.4 or newer. If you're concerned about backwards compatibility with older +versions of Python, use the alternative approach of setting the docstring directly. + +

4.12 Optimized mode

+ + +For improved performance, it may be desirable to use Python's +optimized mode (e.g., running Python with the -O +option). However, doing so causes Python to ignore documentation +strings. This presents special problems for lex.py. To +handle this case, you can create your lexer using +the optimize option as follows: + +
+
+lexer = lex.lex(optimize=1)
+
+
+ +Next, run Python in its normal operating mode. When you do +this, lex.py will write a file called lextab.py to +the current directory. This file contains all of the regular +expression rules and tables used during lexing. On subsequent +executions, +lextab.py will simply be imported to build the lexer. This +approach substantially improves the startup time of the lexer and it +works in Python's optimized mode. + +

+To change the name of the lexer-generated file, use the lextab keyword argument. For example: + +

+
+lexer = lex.lex(optimize=1,lextab="footab")
+
+
+ +When running in optimized mode, it is important to note that lex disables most error checking. Thus, this is really only recommended +if you're sure everything is working correctly and you're ready to start releasing production code. + +

4.13 Debugging

+ + +For the purpose of debugging, you can run lex() in a debugging mode as follows: + +
+
+lexer = lex.lex(debug=1)
+
+
+ +

+This will produce various sorts of debugging information including all of the added rules, +the master regular expressions used by the lexer, and tokens generating during lexing. +

+ +

+In addition, lex.py comes with a simple main function which +will either tokenize input read from standard input or from a file specified +on the command line. To use it, simply put this in your lexer: +

+ +
+
+if __name__ == '__main__':
+     lex.runmain()
+
+
+ +Please refer to the "Debugging" section near the end for some more advanced details +of debugging. + +

4.14 Alternative specification of lexers

+ + +As shown in the example, lexers are specified all within one Python module. If you want to +put token rules in a different module from the one in which you invoke lex(), use the +module keyword argument. + +

+For example, you might have a dedicated module that just contains +the token rules: + +

+
+# module: tokrules.py
+# This module just contains the lexing rules
+
+# List of token names.   This is always required
+tokens = (
+   'NUMBER',
+   'PLUS',
+   'MINUS',
+   'TIMES',
+   'DIVIDE',
+   'LPAREN',
+   'RPAREN',
+)
+
+# Regular expression rules for simple tokens
+t_PLUS    = r'\+'
+t_MINUS   = r'-'
+t_TIMES   = r'\*'
+t_DIVIDE  = r'/'
+t_LPAREN  = r'\('
+t_RPAREN  = r'\)'
+
+# A regular expression rule with some action code
+def t_NUMBER(t):
+    r'\d+'
+    t.value = int(t.value)    
+    return t
+
+# Define a rule so we can track line numbers
+def t_newline(t):
+    r'\n+'
+    t.lexer.lineno += len(t.value)
+
+# A string containing ignored characters (spaces and tabs)
+t_ignore  = ' \t'
+
+# Error handling rule
+def t_error(t):
+    print "Illegal character '%s'" % t.value[0]
+    t.lexer.skip(1)
+
+
+ +Now, if you wanted to build a tokenizer from these rules from within a different module, you would do the following (shown for Python interactive mode): + +
+
+>>> import tokrules
+>>> lexer = lex.lex(module=tokrules)
+>>> lexer.input("3 + 4")
+>>> lexer.token()
+LexToken(NUMBER,3,1,1,0)
+>>> lexer.token()
+LexToken(PLUS,'+',1,2)
+>>> lexer.token()
+LexToken(NUMBER,4,1,4)
+>>> lexer.token()
+None
+>>>
+
+
+ +The module option can also be used to define lexers from instances of a class. For example: + +
+
+import ply.lex as lex
+
+class MyLexer:
+    # List of token names.   This is always required
+    tokens = (
+       'NUMBER',
+       'PLUS',
+       'MINUS',
+       'TIMES',
+       'DIVIDE',
+       'LPAREN',
+       'RPAREN',
+    )
+
+    # Regular expression rules for simple tokens
+    t_PLUS    = r'\+'
+    t_MINUS   = r'-'
+    t_TIMES   = r'\*'
+    t_DIVIDE  = r'/'
+    t_LPAREN  = r'\('
+    t_RPAREN  = r'\)'
+
+    # A regular expression rule with some action code
+    # Note addition of self parameter since we're in a class
+    def t_NUMBER(self,t):
+        r'\d+'
+        t.value = int(t.value)    
+        return t
+
+    # Define a rule so we can track line numbers
+    def t_newline(self,t):
+        r'\n+'
+        t.lexer.lineno += len(t.value)
+
+    # A string containing ignored characters (spaces and tabs)
+    t_ignore  = ' \t'
+
+    # Error handling rule
+    def t_error(self,t):
+        print "Illegal character '%s'" % t.value[0]
+        t.lexer.skip(1)
+
+    # Build the lexer
+    def build(self,**kwargs):
+        self.lexer = lex.lex(module=self, **kwargs)
+    
+    # Test it output
+    def test(self,data):
+        self.lexer.input(data)
+        while True:
+             tok = lexer.token()
+             if not tok: break
+             print tok
+
+# Build the lexer and try it out
+m = MyLexer()
+m.build()           # Build the lexer
+m.test("3 + 4")     # Test it
+
+
+ + +When building a lexer from class, you should construct the lexer from +an instance of the class, not the class object itself. This is because +PLY only works properly if the lexer actions are defined by bound-methods. + +

+When using the module option to lex(), PLY collects symbols +from the underlying object using the dir() function. There is no +direct access to the __dict__ attribute of the object supplied as a +module value. + +

+Finally, if you want to keep things nicely encapsulated, but don't want to use a +full-fledged class definition, lexers can be defined using closures. For example: + +

+
+import ply.lex as lex
+
+# List of token names.   This is always required
+tokens = (
+  'NUMBER',
+  'PLUS',
+  'MINUS',
+  'TIMES',
+  'DIVIDE',
+  'LPAREN',
+  'RPAREN',
+)
+
+def MyLexer():
+    # Regular expression rules for simple tokens
+    t_PLUS    = r'\+'
+    t_MINUS   = r'-'
+    t_TIMES   = r'\*'
+    t_DIVIDE  = r'/'
+    t_LPAREN  = r'\('
+    t_RPAREN  = r'\)'
+
+    # A regular expression rule with some action code
+    def t_NUMBER(t):
+        r'\d+'
+        t.value = int(t.value)    
+        return t
+
+    # Define a rule so we can track line numbers
+    def t_newline(t):
+        r'\n+'
+        t.lexer.lineno += len(t.value)
+
+    # A string containing ignored characters (spaces and tabs)
+    t_ignore  = ' \t'
+
+    # Error handling rule
+    def t_error(t):
+        print "Illegal character '%s'" % t.value[0]
+        t.lexer.skip(1)
+
+    # Build the lexer from my environment and return it    
+    return lex.lex()
+
+
+ + +

4.15 Maintaining state

+ + +In your lexer, you may want to maintain a variety of state +information. This might include mode settings, symbol tables, and +other details. As an example, suppose that you wanted to keep +track of how many NUMBER tokens had been encountered. + +

+One way to do this is to keep a set of global variables in the module +where you created the lexer. For example: + +

+
+num_count = 0
+def t_NUMBER(t):
+    r'\d+'
+    global num_count
+    num_count += 1
+    t.value = int(t.value)    
+    return t
+
+
+ +If you don't like the use of a global variable, another place to store +information is inside the Lexer object created by lex(). +To this, you can use the lexer attribute of tokens passed to +the various rules. For example: + +
+
+def t_NUMBER(t):
+    r'\d+'
+    t.lexer.num_count += 1     # Note use of lexer attribute
+    t.value = int(t.value)    
+    return t
+
+lexer = lex.lex()
+lexer.num_count = 0            # Set the initial count
+
+
+ +This latter approach has the advantage of being simple and working +correctly in applications where multiple instantiations of a given +lexer exist in the same application. However, this might also feel +like a gross violation of encapsulation to OO purists. +Just to put your mind at some ease, all +internal attributes of the lexer (with the exception of lineno) have names that are prefixed +by lex (e.g., lexdata,lexpos, etc.). Thus, +it is perfectly safe to store attributes in the lexer that +don't have names starting with that prefix or a name that conlicts with one of the +predefined methods (e.g., input(), token(), etc.). + +

+If you don't like assigning values on the lexer object, you can define your lexer as a class as +shown in the previous section: + +

+
+class MyLexer:
+    ...
+    def t_NUMBER(self,t):
+        r'\d+'
+        self.num_count += 1
+        t.value = int(t.value)    
+        return t
+
+    def build(self, **kwargs):
+        self.lexer = lex.lex(object=self,**kwargs)
+
+    def __init__(self):
+        self.num_count = 0
+
+
+ +The class approach may be the easiest to manage if your application is +going to be creating multiple instances of the same lexer and you need +to manage a lot of state. + +

+State can also be managed through closures. For example, in Python 3: + +

+
+def MyLexer():
+    num_count = 0
+    ...
+    def t_NUMBER(t):
+        r'\d+'
+        nonlocal num_count
+        num_count += 1
+        t.value = int(t.value)    
+        return t
+    ...
+
+
+ +

4.16 Lexer cloning

+ + +

+If necessary, a lexer object can be duplicated by invoking its clone() method. For example: + +

+
+lexer = lex.lex()
+...
+newlexer = lexer.clone()
+
+
+ +When a lexer is cloned, the copy is exactly identical to the original lexer +including any input text and internal state. However, the clone allows a +different set of input text to be supplied which may be processed separately. +This may be useful in situations when you are writing a parser/compiler that +involves recursive or reentrant processing. For instance, if you +needed to scan ahead in the input for some reason, you could create a +clone and use it to look ahead. Or, if you were implementing some kind of preprocessor, +cloned lexers could be used to handle different input files. + +

+Creating a clone is different than calling lex.lex() in that +PLY doesn't regenerate any of the internal tables or regular expressions. So, + +

+Special considerations need to be made when cloning lexers that also +maintain their own internal state using classes or closures. Namely, +you need to be aware that the newly created lexers will share all of +this state with the original lexer. For example, if you defined a +lexer as a class and did this: + +

+
+m = MyLexer()
+a = lex.lex(object=m)      # Create a lexer
+
+b = a.clone()              # Clone the lexer
+
+
+ +Then both a and b are going to be bound to the same +object m and any changes to m will be reflected in both lexers. It's +important to emphasize that clone() is only meant to create a new lexer +that reuses the regular expressions and environment of another lexer. If you +need to make a totally new copy of a lexer, then call lex() again. + +

4.17 Internal lexer state

+ + +A Lexer object lexer has a number of internal attributes that may be useful in certain +situations. + +

+lexer.lexpos +

+This attribute is an integer that contains the current position within the input text. If you modify +the value, it will change the result of the next call to token(). Within token rule functions, this points +to the first character after the matched text. If the value is modified within a rule, the next returned token will be +matched at the new position. +
+ +

+lexer.lineno +

+The current value of the line number attribute stored in the lexer. PLY only specifies that the attribute +exists---it never sets, updates, or performs any processing with it. If you want to track line numbers, +you will need to add code yourself (see the section on line numbers and positional information). +
+ +

+lexer.lexdata +

+The current input text stored in the lexer. This is the string passed with the input() method. It +would probably be a bad idea to modify this unless you really know what you're doing. +
+ +

+lexer.lexmatch +

+This is the raw Match object returned by the Python re.match() function (used internally by PLY) for the +current token. If you have written a regular expression that contains named groups, you can use this to retrieve those values. +Note: This attribute is only updated when tokens are defined and processed by functions. +
+ +

4.18 Conditional lexing and start conditions

+ + +In advanced parsing applications, it may be useful to have different +lexing states. For instance, you may want the occurrence of a certain +token or syntactic construct to trigger a different kind of lexing. +PLY supports a feature that allows the underlying lexer to be put into +a series of different states. Each state can have its own tokens, +lexing rules, and so forth. The implementation is based largely on +the "start condition" feature of GNU flex. Details of this can be found +at http://www.gnu.org/software/flex/manual/html_chapter/flex_11.html.. + +

+To define a new lexing state, it must first be declared. This is done by including a "states" declaration in your +lex file. For example: + +

+
+states = (
+   ('foo','exclusive'),
+   ('bar','inclusive'),
+)
+
+
+ +This declaration declares two states, 'foo' +and 'bar'. States may be of two types; 'exclusive' +and 'inclusive'. An exclusive state completely overrides the +default behavior of the lexer. That is, lex will only return tokens +and apply rules defined specifically for that state. An inclusive +state adds additional tokens and rules to the default set of rules. +Thus, lex will return both the tokens defined by default in addition +to those defined for the inclusive state. + +

+Once a state has been declared, tokens and rules are declared by including the +state name in token/rule declaration. For example: + +

+
+t_foo_NUMBER = r'\d+'                      # Token 'NUMBER' in state 'foo'        
+t_bar_ID     = r'[a-zA-Z_][a-zA-Z0-9_]*'   # Token 'ID' in state 'bar'
+
+def t_foo_newline(t):
+    r'\n'
+    t.lexer.lineno += 1
+
+
+ +A token can be declared in multiple states by including multiple state names in the declaration. For example: + +
+
+t_foo_bar_NUMBER = r'\d+'         # Defines token 'NUMBER' in both state 'foo' and 'bar'
+
+
+ +Alternative, a token can be declared in all states using the 'ANY' in the name. + +
+
+t_ANY_NUMBER = r'\d+'         # Defines a token 'NUMBER' in all states
+
+
+ +If no state name is supplied, as is normally the case, the token is associated with a special state 'INITIAL'. For example, +these two declarations are identical: + +
+
+t_NUMBER = r'\d+'
+t_INITIAL_NUMBER = r'\d+'
+
+
+ +

+States are also associated with the special t_ignore and t_error() declarations. For example, if a state treats +these differently, you can declare: + +

+
+t_foo_ignore = " \t\n"       # Ignored characters for state 'foo'
+
+def t_bar_error(t):          # Special error handler for state 'bar'
+    pass 
+
+
+ +By default, lexing operates in the 'INITIAL' state. This state includes all of the normally defined tokens. +For users who aren't using different states, this fact is completely transparent. If, during lexing or parsing, you want to change +the lexing state, use the begin() method. For example: + +
+
+def t_begin_foo(t):
+    r'start_foo'
+    t.lexer.begin('foo')             # Starts 'foo' state
+
+
+ +To get out of a state, you use begin() to switch back to the initial state. For example: + +
+
+def t_foo_end(t):
+    r'end_foo'
+    t.lexer.begin('INITIAL')        # Back to the initial state
+
+
+ +The management of states can also be done with a stack. For example: + +
+
+def t_begin_foo(t):
+    r'start_foo'
+    t.lexer.push_state('foo')             # Starts 'foo' state
+
+def t_foo_end(t):
+    r'end_foo'
+    t.lexer.pop_state()                   # Back to the previous state
+
+
+ +

+The use of a stack would be useful in situations where there are many ways of entering a new lexing state and you merely want to go back +to the previous state afterwards. + +

+An example might help clarify. Suppose you were writing a parser and you wanted to grab sections of arbitrary C code enclosed by +curly braces. That is, whenever you encounter a starting brace '{', you want to read all of the enclosed code up to the ending brace '}' +and return it as a string. Doing this with a normal regular expression rule is nearly (if not actually) impossible. This is because braces can +be nested and can be included in comments and strings. Thus, simply matching up to the first matching '}' character isn't good enough. Here is how +you might use lexer states to do this: + +

+
+# Declare the state
+states = (
+  ('ccode','exclusive'),
+)
+
+# Match the first {. Enter ccode state.
+def t_ccode(t):
+    r'\{'
+    t.lexer.code_start = t.lexer.lexpos        # Record the starting position
+    t.lexer.level = 1                          # Initial brace level
+    t.lexer.begin('ccode')                     # Enter 'ccode' state
+
+# Rules for the ccode state
+def t_ccode_lbrace(t):     
+    r'\{'
+    t.lexer.level +=1                
+
+def t_ccode_rbrace(t):
+    r'\}'
+    t.lexer.level -=1
+
+    # If closing brace, return the code fragment
+    if t.lexer.level == 0:
+         t.value = t.lexer.lexdata[t.lexer.code_start:t.lexer.lexpos+1]
+         t.type = "CCODE"
+         t.lexer.lineno += t.value.count('\n')
+         t.lexer.begin('INITIAL')           
+         return t
+
+# C or C++ comment (ignore)    
+def t_ccode_comment(t):
+    r'(/\*(.|\n)*?*/)|(//.*)'
+    pass
+
+# C string
+def t_ccode_string(t):
+   r'\"([^\\\n]|(\\.))*?\"'
+
+# C character literal
+def t_ccode_char(t):
+   r'\'([^\\\n]|(\\.))*?\''
+
+# Any sequence of non-whitespace characters (not braces, strings)
+def t_ccode_nonspace(t):
+   r'[^\s\{\}\'\"]+'
+
+# Ignored characters (whitespace)
+t_ccode_ignore = " \t\n"
+
+# For bad characters, we just skip over it
+def t_ccode_error(t):
+    t.lexer.skip(1)
+
+
+ +In this example, the occurrence of the first '{' causes the lexer to record the starting position and enter a new state 'ccode'. A collection of rules then match +various parts of the input that follow (comments, strings, etc.). All of these rules merely discard the token (by not returning a value). +However, if the closing right brace is encountered, the rule t_ccode_rbrace collects all of the code (using the earlier recorded starting +position), stores it, and returns a token 'CCODE' containing all of that text. When returning the token, the lexing state is restored back to its +initial state. + +

4.19 Miscellaneous Issues

+ + +

+

  • The lexer requires input to be supplied as a single input string. Since most machines have more than enough memory, this +rarely presents a performance concern. However, it means that the lexer currently can't be used with streaming data +such as open files or sockets. This limitation is primarily a side-effect of using the re module. + +

    +

  • The lexer should work properly with both Unicode strings given as token and pattern matching rules as +well as for input text. + +

    +

  • If you need to supply optional flags to the re.compile() function, use the reflags option to lex. For example: + +
    +
    +lex.lex(reflags=re.UNICODE)
    +
    +
    + +

    +

  • Since the lexer is written entirely in Python, its performance is +largely determined by that of the Python re module. Although +the lexer has been written to be as efficient as possible, it's not +blazingly fast when used on very large input files. If +performance is concern, you might consider upgrading to the most +recent version of Python, creating a hand-written lexer, or offloading +the lexer into a C extension module. + +

    +If you are going to create a hand-written lexer and you plan to use it with yacc.py, +it only needs to conform to the following requirements: + +

      +
    • It must provide a token() method that returns the next token or None if no more +tokens are available. +
    • The token() method must return an object tok that has type and value attributes. +
    + +

    5. Parsing basics

    + + +yacc.py is used to parse language syntax. Before showing an +example, there are a few important bits of background that must be +mentioned. First, syntax is usually specified in terms of a BNF grammar. +For example, if you wanted to parse +simple arithmetic expressions, you might first write an unambiguous +grammar specification like this: + +
    +
     
    +expression : expression + term
    +           | expression - term
    +           | term
    +
    +term       : term * factor
    +           | term / factor
    +           | factor
    +
    +factor     : NUMBER
    +           | ( expression )
    +
    +
    + +In the grammar, symbols such as NUMBER, +, -, *, and / are known +as terminals and correspond to raw input tokens. Identifiers such as term and factor refer to +grammar rules comprised of a collection of terminals and other rules. These identifiers are known as non-terminals. +

    + +The semantic behavior of a language is often specified using a +technique known as syntax directed translation. In syntax directed +translation, attributes are attached to each symbol in a given grammar +rule along with an action. Whenever a particular grammar rule is +recognized, the action describes what to do. For example, given the +expression grammar above, you might write the specification for a +simple calculator like this: + +

    +
     
    +Grammar                             Action
    +--------------------------------    -------------------------------------------- 
    +expression0 : expression1 + term    expression0.val = expression1.val + term.val
    +            | expression1 - term    expression0.val = expression1.val - term.val
    +            | term                  expression0.val = term.val
    +
    +term0       : term1 * factor        term0.val = term1.val * factor.val
    +            | term1 / factor        term0.val = term1.val / factor.val
    +            | factor                term0.val = factor.val
    +
    +factor      : NUMBER                factor.val = int(NUMBER.lexval)
    +            | ( expression )        factor.val = expression.val
    +
    +
    + +A good way to think about syntax directed translation is to +view each symbol in the grammar as a kind of object. Associated +with each symbol is a value representing its "state" (for example, the +val attribute above). Semantic +actions are then expressed as a collection of functions or methods +that operate on the symbols and associated values. + +

    +Yacc uses a parsing technique known as LR-parsing or shift-reduce parsing. LR parsing is a +bottom up technique that tries to recognize the right-hand-side of various grammar rules. +Whenever a valid right-hand-side is found in the input, the appropriate action code is triggered and the +grammar symbols are replaced by the grammar symbol on the left-hand-side. + +

    +LR parsing is commonly implemented by shifting grammar symbols onto a +stack and looking at the stack and the next input token for patterns that +match one of the grammar rules. +The details of the algorithm can be found in a compiler textbook, but the +following example illustrates the steps that are performed if you +wanted to parse the expression +3 + 5 * (10 - 20) using the grammar defined above. In the example, +the special symbol $ represents the end of input. + + +

    +
    +Step Symbol Stack           Input Tokens            Action
    +---- ---------------------  ---------------------   -------------------------------
    +1                           3 + 5 * ( 10 - 20 )$    Shift 3
    +2    3                        + 5 * ( 10 - 20 )$    Reduce factor : NUMBER
    +3    factor                   + 5 * ( 10 - 20 )$    Reduce term   : factor
    +4    term                     + 5 * ( 10 - 20 )$    Reduce expr : term
    +5    expr                     + 5 * ( 10 - 20 )$    Shift +
    +6    expr +                     5 * ( 10 - 20 )$    Shift 5
    +7    expr + 5                     * ( 10 - 20 )$    Reduce factor : NUMBER
    +8    expr + factor                * ( 10 - 20 )$    Reduce term   : factor
    +9    expr + term                  * ( 10 - 20 )$    Shift *
    +10   expr + term *                  ( 10 - 20 )$    Shift (
    +11   expr + term * (                  10 - 20 )$    Shift 10
    +12   expr + term * ( 10                  - 20 )$    Reduce factor : NUMBER
    +13   expr + term * ( factor              - 20 )$    Reduce term : factor
    +14   expr + term * ( term                - 20 )$    Reduce expr : term
    +15   expr + term * ( expr                - 20 )$    Shift -
    +16   expr + term * ( expr -                20 )$    Shift 20
    +17   expr + term * ( expr - 20                )$    Reduce factor : NUMBER
    +18   expr + term * ( expr - factor            )$    Reduce term : factor
    +19   expr + term * ( expr - term              )$    Reduce expr : expr - term
    +20   expr + term * ( expr                     )$    Shift )
    +21   expr + term * ( expr )                    $    Reduce factor : (expr)
    +22   expr + term * factor                      $    Reduce term : term * factor
    +23   expr + term                               $    Reduce expr : expr + term
    +24   expr                                      $    Reduce expr
    +25                                             $    Success!
    +
    +
    + +When parsing the expression, an underlying state machine and the +current input token determine what happens next. If the next token +looks like part of a valid grammar rule (based on other items on the +stack), it is generally shifted onto the stack. If the top of the +stack contains a valid right-hand-side of a grammar rule, it is +usually "reduced" and the symbols replaced with the symbol on the +left-hand-side. When this reduction occurs, the appropriate action is +triggered (if defined). If the input token can't be shifted and the +top of stack doesn't match any grammar rules, a syntax error has +occurred and the parser must take some kind of recovery step (or bail +out). A parse is only successful if the parser reaches a state where +the symbol stack is empty and there are no more input tokens. + +

    +It is important to note that the underlying implementation is built +around a large finite-state machine that is encoded in a collection of +tables. The construction of these tables is non-trivial and +beyond the scope of this discussion. However, subtle details of this +process explain why, in the example above, the parser chooses to shift +a token onto the stack in step 9 rather than reducing the +rule expr : expr + term. + +

    6. Yacc

    + + +The ply.yacc module implements the parsing component of PLY. +The name "yacc" stands for "Yet Another Compiler Compiler" and is +borrowed from the Unix tool of the same name. + +

    6.1 An example

    + + +Suppose you wanted to make a grammar for simple arithmetic expressions as previously described. Here is +how you would do it with yacc.py: + +
    +
    +# Yacc example
    +
    +import ply.yacc as yacc
    +
    +# Get the token map from the lexer.  This is required.
    +from calclex import tokens
    +
    +def p_expression_plus(p):
    +    'expression : expression PLUS term'
    +    p[0] = p[1] + p[3]
    +
    +def p_expression_minus(p):
    +    'expression : expression MINUS term'
    +    p[0] = p[1] - p[3]
    +
    +def p_expression_term(p):
    +    'expression : term'
    +    p[0] = p[1]
    +
    +def p_term_times(p):
    +    'term : term TIMES factor'
    +    p[0] = p[1] * p[3]
    +
    +def p_term_div(p):
    +    'term : term DIVIDE factor'
    +    p[0] = p[1] / p[3]
    +
    +def p_term_factor(p):
    +    'term : factor'
    +    p[0] = p[1]
    +
    +def p_factor_num(p):
    +    'factor : NUMBER'
    +    p[0] = p[1]
    +
    +def p_factor_expr(p):
    +    'factor : LPAREN expression RPAREN'
    +    p[0] = p[2]
    +
    +# Error rule for syntax errors
    +def p_error(p):
    +    print "Syntax error in input!"
    +
    +# Build the parser
    +parser = yacc.yacc()
    +
    +while True:
    +   try:
    +       s = raw_input('calc > ')
    +   except EOFError:
    +       break
    +   if not s: continue
    +   result = parser.parse(s)
    +   print result
    +
    +
    + +In this example, each grammar rule is defined by a Python function +where the docstring to that function contains the appropriate +context-free grammar specification. The statements that make up the +function body implement the semantic actions of the rule. Each function +accepts a single argument p that is a sequence containing the +values of each grammar symbol in the corresponding rule. The values +of p[i] are mapped to grammar symbols as shown here: + +
    +
    +def p_expression_plus(p):
    +    'expression : expression PLUS term'
    +    #   ^            ^        ^    ^
    +    #  p[0]         p[1]     p[2] p[3]
    +
    +    p[0] = p[1] + p[3]
    +
    +
    + +

    +For tokens, the "value" of the corresponding p[i] is the +same as the p.value attribute assigned in the lexer +module. For non-terminals, the value is determined by whatever is +placed in p[0] when rules are reduced. This value can be +anything at all. However, it probably most common for the value to be +a simple Python type, a tuple, or an instance. In this example, we +are relying on the fact that the NUMBER token stores an +integer value in its value field. All of the other rules simply +perform various types of integer operations and propagate the result. +

    + +

    +Note: The use of negative indices have a special meaning in +yacc---specially p[-1] does not have the same value +as p[3] in this example. Please see the section on "Embedded +Actions" for further details. +

    + +

    +The first rule defined in the yacc specification determines the +starting grammar symbol (in this case, a rule for expression +appears first). Whenever the starting rule is reduced by the parser +and no more input is available, parsing stops and the final value is +returned (this value will be whatever the top-most rule placed +in p[0]). Note: an alternative starting symbol can be +specified using the start keyword argument to +yacc(). + +

    The p_error(p) rule is defined to catch syntax errors. +See the error handling section below for more detail. + +

    +To build the parser, call the yacc.yacc() function. This +function looks at the module and attempts to construct all of the LR +parsing tables for the grammar you have specified. The first +time yacc.yacc() is invoked, you will get a message such as +this: + +

    +
    +$ python calcparse.py
    +Generating LALR tables
    +calc > 
    +
    +
    + +Since table construction is relatively expensive (especially for large +grammars), the resulting parsing table is written to the current +directory in a file called parsetab.py. In addition, a +debugging file called parser.out is created. On subsequent +executions, yacc will reload the table from +parsetab.py unless it has detected a change in the underlying +grammar (in which case the tables and parsetab.py file are +regenerated). Note: The names of parser output files can be changed +if necessary. See the PLY Reference for details. + +

    +If any errors are detected in your grammar specification, yacc.py will produce +diagnostic messages and possibly raise an exception. Some of the errors that can be detected include: + +

      +
    • Duplicated function names (if more than one rule function have the same name in the grammar file). +
    • Shift/reduce and reduce/reduce conflicts generated by ambiguous grammars. +
    • Badly specified grammar rules. +
    • Infinite recursion (rules that can never terminate). +
    • Unused rules and tokens +
    • Undefined rules and tokens +
    + +The next few sections discuss grammar specification in more detail. + +

    +The final part of the example shows how to actually run the parser +created by +yacc(). To run the parser, you simply have to call +the parse() with a string of input text. This will run all +of the grammar rules and return the result of the entire parse. This +result return is the value assigned to p[0] in the starting +grammar rule. + +

    6.2 Combining Grammar Rule Functions

    + + +When grammar rules are similar, they can be combined into a single function. +For example, consider the two rules in our earlier example: + +
    +
    +def p_expression_plus(p):
    +    'expression : expression PLUS term'
    +    p[0] = p[1] + p[3]
    +
    +def p_expression_minus(t):
    +    'expression : expression MINUS term'
    +    p[0] = p[1] - p[3]
    +
    +
    + +Instead of writing two functions, you might write a single function like this: + +
    +
    +def p_expression(p):
    +    '''expression : expression PLUS term
    +                  | expression MINUS term'''
    +    if p[2] == '+':
    +        p[0] = p[1] + p[3]
    +    elif p[2] == '-':
    +        p[0] = p[1] - p[3]
    +
    +
    + +In general, the doc string for any given function can contain multiple grammar rules. So, it would +have also been legal (although possibly confusing) to write this: + +
    +
    +def p_binary_operators(p):
    +    '''expression : expression PLUS term
    +                  | expression MINUS term
    +       term       : term TIMES factor
    +                  | term DIVIDE factor'''
    +    if p[2] == '+':
    +        p[0] = p[1] + p[3]
    +    elif p[2] == '-':
    +        p[0] = p[1] - p[3]
    +    elif p[2] == '*':
    +        p[0] = p[1] * p[3]
    +    elif p[2] == '/':
    +        p[0] = p[1] / p[3]
    +
    +
    + +When combining grammar rules into a single function, it is usually a good idea for all of the rules to have +a similar structure (e.g., the same number of terms). Otherwise, the corresponding action code may be more +complicated than necessary. However, it is possible to handle simple cases using len(). For example: + +
    +
    +def p_expressions(p):
    +    '''expression : expression MINUS expression
    +                  | MINUS expression'''
    +    if (len(p) == 4):
    +        p[0] = p[1] - p[3]
    +    elif (len(p) == 3):
    +        p[0] = -p[2]
    +
    +
    + +If parsing performance is a concern, you should resist the urge to put +too much conditional processing into a single grammar rule as shown in +these examples. When you add checks to see which grammar rule is +being handled, you are actually duplicating the work that the parser +has already performed (i.e., the parser already knows exactly what rule it +matched). You can eliminate this overhead by using a +separate p_rule() function for each grammar rule. + +

    6.3 Character Literals

    + + +If desired, a grammar may contain tokens defined as single character literals. For example: + +
    +
    +def p_binary_operators(p):
    +    '''expression : expression '+' term
    +                  | expression '-' term
    +       term       : term '*' factor
    +                  | term '/' factor'''
    +    if p[2] == '+':
    +        p[0] = p[1] + p[3]
    +    elif p[2] == '-':
    +        p[0] = p[1] - p[3]
    +    elif p[2] == '*':
    +        p[0] = p[1] * p[3]
    +    elif p[2] == '/':
    +        p[0] = p[1] / p[3]
    +
    +
    + +A character literal must be enclosed in quotes such as '+'. In addition, if literals are used, they must be declared in the +corresponding lex file through the use of a special literals declaration. + +
    +
    +# Literals.  Should be placed in module given to lex()
    +literals = ['+','-','*','/' ]
    +
    +
    + +Character literals are limited to a single character. Thus, it is not legal to specify literals such as '<=' or '=='. For this, use +the normal lexing rules (e.g., define a rule such as t_EQ = r'=='). + +

    6.4 Empty Productions

    + + +yacc.py can handle empty productions by defining a rule like this: + +
    +
    +def p_empty(p):
    +    'empty :'
    +    pass
    +
    +
    + +Now to use the empty production, simply use 'empty' as a symbol. For example: + +
    +
    +def p_optitem(p):
    +    'optitem : item'
    +    '        | empty'
    +    ...
    +
    +
    + +Note: You can write empty rules anywhere by simply specifying an empty +right hand side. However, I personally find that writing an "empty" +rule and using "empty" to denote an empty production is easier to read +and more clearly states your intentions. + +

    6.5 Changing the starting symbol

    + + +Normally, the first rule found in a yacc specification defines the starting grammar rule (top level rule). To change this, simply +supply a start specifier in your file. For example: + +
    +
    +start = 'foo'
    +
    +def p_bar(p):
    +    'bar : A B'
    +
    +# This is the starting rule due to the start specifier above
    +def p_foo(p):
    +    'foo : bar X'
    +...
    +
    +
    + +The use of a start specifier may be useful during debugging +since you can use it to have yacc build a subset of a larger grammar. +For this purpose, it is also possible to specify a starting symbol as +an argument to yacc(). For example: + +
    +
    +yacc.yacc(start='foo')
    +
    +
    + +

    6.6 Dealing With Ambiguous Grammars

    + + +The expression grammar given in the earlier example has been written +in a special format to eliminate ambiguity. However, in many +situations, it is extremely difficult or awkward to write grammars in +this format. A much more natural way to express the grammar is in a +more compact form like this: + +
    +
    +expression : expression PLUS expression
    +           | expression MINUS expression
    +           | expression TIMES expression
    +           | expression DIVIDE expression
    +           | LPAREN expression RPAREN
    +           | NUMBER
    +
    +
    + +Unfortunately, this grammar specification is ambiguous. For example, +if you are parsing the string "3 * 4 + 5", there is no way to tell how +the operators are supposed to be grouped. For example, does the +expression mean "(3 * 4) + 5" or is it "3 * (4+5)"? + +

    +When an ambiguous grammar is given to yacc.py it will print +messages about "shift/reduce conflicts" or "reduce/reduce conflicts". +A shift/reduce conflict is caused when the parser generator can't +decide whether or not to reduce a rule or shift a symbol on the +parsing stack. For example, consider the string "3 * 4 + 5" and the +internal parsing stack: + +

    +
    +Step Symbol Stack           Input Tokens            Action
    +---- ---------------------  ---------------------   -------------------------------
    +1    $                                3 * 4 + 5$    Shift 3
    +2    $ 3                                * 4 + 5$    Reduce : expression : NUMBER
    +3    $ expr                             * 4 + 5$    Shift *
    +4    $ expr *                             4 + 5$    Shift 4
    +5    $ expr * 4                             + 5$    Reduce: expression : NUMBER
    +6    $ expr * expr                          + 5$    SHIFT/REDUCE CONFLICT ????
    +
    +
    + +In this case, when the parser reaches step 6, it has two options. One +is to reduce the rule expr : expr * expr on the stack. The +other option is to shift the token + on the stack. Both +options are perfectly legal from the rules of the +context-free-grammar. + +

    +By default, all shift/reduce conflicts are resolved in favor of +shifting. Therefore, in the above example, the parser will always +shift the + instead of reducing. Although this strategy +works in many cases (for example, the case of +"if-then" versus "if-then-else"), it is not enough for arithmetic expressions. In fact, +in the above example, the decision to shift + is completely +wrong---we should have reduced expr * expr since +multiplication has higher mathematical precedence than addition. + +

    To resolve ambiguity, especially in expression +grammars, yacc.py allows individual tokens to be assigned a +precedence level and associativity. This is done by adding a variable +precedence to the grammar file like this: + +

    +
    +precedence = (
    +    ('left', 'PLUS', 'MINUS'),
    +    ('left', 'TIMES', 'DIVIDE'),
    +)
    +
    +
    + +This declaration specifies that PLUS/MINUS have the +same precedence level and are left-associative and that +TIMES/DIVIDE have the same precedence and are +left-associative. Within the precedence declaration, tokens +are ordered from lowest to highest precedence. Thus, this declaration +specifies that TIMES/DIVIDE have higher precedence +than PLUS/MINUS (since they appear later in the +precedence specification). + +

    +The precedence specification works by associating a numerical +precedence level value and associativity direction to the listed +tokens. For example, in the above example you get: + +

    +
    +PLUS      : level = 1,  assoc = 'left'
    +MINUS     : level = 1,  assoc = 'left'
    +TIMES     : level = 2,  assoc = 'left'
    +DIVIDE    : level = 2,  assoc = 'left'
    +
    +
    + +These values are then used to attach a numerical precedence value and +associativity direction to each grammar rule. This is always +determined by looking at the precedence of the right-most terminal +symbol. For example: + +
    +
    +expression : expression PLUS expression                 # level = 1, left
    +           | expression MINUS expression                # level = 1, left
    +           | expression TIMES expression                # level = 2, left
    +           | expression DIVIDE expression               # level = 2, left
    +           | LPAREN expression RPAREN                   # level = None (not specified)
    +           | NUMBER                                     # level = None (not specified)
    +
    +
    + +When shift/reduce conflicts are encountered, the parser generator resolves the conflict by +looking at the precedence rules and associativity specifiers. + +

    +

      +
    1. If the current token has higher precedence than the rule on the stack, it is shifted. +
    2. If the grammar rule on the stack has higher precedence, the rule is reduced. +
    3. If the current token and the grammar rule have the same precedence, the +rule is reduced for left associativity, whereas the token is shifted for right associativity. +
    4. If nothing is known about the precedence, shift/reduce conflicts are resolved in +favor of shifting (the default). +
    + +For example, if "expression PLUS expression" has been parsed and the +next token is "TIMES", the action is going to be a shift because +"TIMES" has a higher precedence level than "PLUS". On the other hand, +if "expression TIMES expression" has been parsed and the next token is +"PLUS", the action is going to be reduce because "PLUS" has a lower +precedence than "TIMES." + +

    +When shift/reduce conflicts are resolved using the first three +techniques (with the help of precedence rules), yacc.py will +report no errors or conflicts in the grammar (although it will print +some information in the parser.out debugging file). + +

    +One problem with the precedence specifier technique is that it is +sometimes necessary to change the precedence of an operator in certain +contexts. For example, consider a unary-minus operator in "3 + 4 * +-5". Mathematically, the unary minus is normally given a very high +precedence--being evaluated before the multiply. However, in our +precedence specifier, MINUS has a lower precedence than TIMES. To +deal with this, precedence rules can be given for so-called "fictitious tokens" +like this: + +

    +
    +precedence = (
    +    ('left', 'PLUS', 'MINUS'),
    +    ('left', 'TIMES', 'DIVIDE'),
    +    ('right', 'UMINUS'),            # Unary minus operator
    +)
    +
    +
    + +Now, in the grammar file, we can write our unary minus rule like this: + +
    +
    +def p_expr_uminus(p):
    +    'expression : MINUS expression %prec UMINUS'
    +    p[0] = -p[2]
    +
    +
    + +In this case, %prec UMINUS overrides the default rule precedence--setting it to that +of UMINUS in the precedence specifier. + +

    +At first, the use of UMINUS in this example may appear very confusing. +UMINUS is not an input token or a grammer rule. Instead, you should +think of it as the name of a special marker in the precedence table. When you use the %prec qualifier, you're simply +telling yacc that you want the precedence of the expression to be the same as for this special marker instead of the usual precedence. + +

    +It is also possible to specify non-associativity in the precedence table. This would +be used when you don't want operations to chain together. For example, suppose +you wanted to support comparison operators like < and > but you didn't want to allow +combinations like a < b < c. To do this, simply specify a rule like this: + +

    +
    +precedence = (
    +    ('nonassoc', 'LESSTHAN', 'GREATERTHAN'),  # Nonassociative operators
    +    ('left', 'PLUS', 'MINUS'),
    +    ('left', 'TIMES', 'DIVIDE'),
    +    ('right', 'UMINUS'),            # Unary minus operator
    +)
    +
    +
    + +

    +If you do this, the occurrence of input text such as a < b < c will result in a syntax error. However, simple +expressions such as a < b will still be fine. + +

    +Reduce/reduce conflicts are caused when there are multiple grammar +rules that can be applied to a given set of symbols. This kind of +conflict is almost always bad and is always resolved by picking the +rule that appears first in the grammar file. Reduce/reduce conflicts +are almost always caused when different sets of grammar rules somehow +generate the same set of symbols. For example: + +

    +
    +assignment :  ID EQUALS NUMBER
    +           |  ID EQUALS expression
    +           
    +expression : expression PLUS expression
    +           | expression MINUS expression
    +           | expression TIMES expression
    +           | expression DIVIDE expression
    +           | LPAREN expression RPAREN
    +           | NUMBER
    +
    +
    + +In this case, a reduce/reduce conflict exists between these two rules: + +
    +
    +assignment  : ID EQUALS NUMBER
    +expression  : NUMBER
    +
    +
    + +For example, if you wrote "a = 5", the parser can't figure out if this +is supposed to be reduced as assignment : ID EQUALS NUMBER or +whether it's supposed to reduce the 5 as an expression and then reduce +the rule assignment : ID EQUALS expression. + +

    +It should be noted that reduce/reduce conflicts are notoriously +difficult to spot simply looking at the input grammer. When a +reduce/reduce conflict occurs, yacc() will try to help by +printing a warning message such as this: + +

    +
    +WARNING: 1 reduce/reduce conflict
    +WARNING: reduce/reduce conflict in state 15 resolved using rule (assignment -> ID EQUALS NUMBER)
    +WARNING: rejected rule (expression -> NUMBER)
    +
    +
    + +This message identifies the two rules that are in conflict. However, +it may not tell you how the parser arrived at such a state. To try +and figure it out, you'll probably have to look at your grammar and +the contents of the +parser.out debugging file with an appropriately high level of +caffeination. + +

    6.7 The parser.out file

    + + +Tracking down shift/reduce and reduce/reduce conflicts is one of the finer pleasures of using an LR +parsing algorithm. To assist in debugging, yacc.py creates a debugging file called +'parser.out' when it generates the parsing table. The contents of this file look like the following: + +
    +
    +Unused terminals:
    +
    +
    +Grammar
    +
    +Rule 1     expression -> expression PLUS expression
    +Rule 2     expression -> expression MINUS expression
    +Rule 3     expression -> expression TIMES expression
    +Rule 4     expression -> expression DIVIDE expression
    +Rule 5     expression -> NUMBER
    +Rule 6     expression -> LPAREN expression RPAREN
    +
    +Terminals, with rules where they appear
    +
    +TIMES                : 3
    +error                : 
    +MINUS                : 2
    +RPAREN               : 6
    +LPAREN               : 6
    +DIVIDE               : 4
    +PLUS                 : 1
    +NUMBER               : 5
    +
    +Nonterminals, with rules where they appear
    +
    +expression           : 1 1 2 2 3 3 4 4 6 0
    +
    +
    +Parsing method: LALR
    +
    +
    +state 0
    +
    +    S' -> . expression
    +    expression -> . expression PLUS expression
    +    expression -> . expression MINUS expression
    +    expression -> . expression TIMES expression
    +    expression -> . expression DIVIDE expression
    +    expression -> . NUMBER
    +    expression -> . LPAREN expression RPAREN
    +
    +    NUMBER          shift and go to state 3
    +    LPAREN          shift and go to state 2
    +
    +
    +state 1
    +
    +    S' -> expression .
    +    expression -> expression . PLUS expression
    +    expression -> expression . MINUS expression
    +    expression -> expression . TIMES expression
    +    expression -> expression . DIVIDE expression
    +
    +    PLUS            shift and go to state 6
    +    MINUS           shift and go to state 5
    +    TIMES           shift and go to state 4
    +    DIVIDE          shift and go to state 7
    +
    +
    +state 2
    +
    +    expression -> LPAREN . expression RPAREN
    +    expression -> . expression PLUS expression
    +    expression -> . expression MINUS expression
    +    expression -> . expression TIMES expression
    +    expression -> . expression DIVIDE expression
    +    expression -> . NUMBER
    +    expression -> . LPAREN expression RPAREN
    +
    +    NUMBER          shift and go to state 3
    +    LPAREN          shift and go to state 2
    +
    +
    +state 3
    +
    +    expression -> NUMBER .
    +
    +    $               reduce using rule 5
    +    PLUS            reduce using rule 5
    +    MINUS           reduce using rule 5
    +    TIMES           reduce using rule 5
    +    DIVIDE          reduce using rule 5
    +    RPAREN          reduce using rule 5
    +
    +
    +state 4
    +
    +    expression -> expression TIMES . expression
    +    expression -> . expression PLUS expression
    +    expression -> . expression MINUS expression
    +    expression -> . expression TIMES expression
    +    expression -> . expression DIVIDE expression
    +    expression -> . NUMBER
    +    expression -> . LPAREN expression RPAREN
    +
    +    NUMBER          shift and go to state 3
    +    LPAREN          shift and go to state 2
    +
    +
    +state 5
    +
    +    expression -> expression MINUS . expression
    +    expression -> . expression PLUS expression
    +    expression -> . expression MINUS expression
    +    expression -> . expression TIMES expression
    +    expression -> . expression DIVIDE expression
    +    expression -> . NUMBER
    +    expression -> . LPAREN expression RPAREN
    +
    +    NUMBER          shift and go to state 3
    +    LPAREN          shift and go to state 2
    +
    +
    +state 6
    +
    +    expression -> expression PLUS . expression
    +    expression -> . expression PLUS expression
    +    expression -> . expression MINUS expression
    +    expression -> . expression TIMES expression
    +    expression -> . expression DIVIDE expression
    +    expression -> . NUMBER
    +    expression -> . LPAREN expression RPAREN
    +
    +    NUMBER          shift and go to state 3
    +    LPAREN          shift and go to state 2
    +
    +
    +state 7
    +
    +    expression -> expression DIVIDE . expression
    +    expression -> . expression PLUS expression
    +    expression -> . expression MINUS expression
    +    expression -> . expression TIMES expression
    +    expression -> . expression DIVIDE expression
    +    expression -> . NUMBER
    +    expression -> . LPAREN expression RPAREN
    +
    +    NUMBER          shift and go to state 3
    +    LPAREN          shift and go to state 2
    +
    +
    +state 8
    +
    +    expression -> LPAREN expression . RPAREN
    +    expression -> expression . PLUS expression
    +    expression -> expression . MINUS expression
    +    expression -> expression . TIMES expression
    +    expression -> expression . DIVIDE expression
    +
    +    RPAREN          shift and go to state 13
    +    PLUS            shift and go to state 6
    +    MINUS           shift and go to state 5
    +    TIMES           shift and go to state 4
    +    DIVIDE          shift and go to state 7
    +
    +
    +state 9
    +
    +    expression -> expression TIMES expression .
    +    expression -> expression . PLUS expression
    +    expression -> expression . MINUS expression
    +    expression -> expression . TIMES expression
    +    expression -> expression . DIVIDE expression
    +
    +    $               reduce using rule 3
    +    PLUS            reduce using rule 3
    +    MINUS           reduce using rule 3
    +    TIMES           reduce using rule 3
    +    DIVIDE          reduce using rule 3
    +    RPAREN          reduce using rule 3
    +
    +  ! PLUS            [ shift and go to state 6 ]
    +  ! MINUS           [ shift and go to state 5 ]
    +  ! TIMES           [ shift and go to state 4 ]
    +  ! DIVIDE          [ shift and go to state 7 ]
    +
    +state 10
    +
    +    expression -> expression MINUS expression .
    +    expression -> expression . PLUS expression
    +    expression -> expression . MINUS expression
    +    expression -> expression . TIMES expression
    +    expression -> expression . DIVIDE expression
    +
    +    $               reduce using rule 2
    +    PLUS            reduce using rule 2
    +    MINUS           reduce using rule 2
    +    RPAREN          reduce using rule 2
    +    TIMES           shift and go to state 4
    +    DIVIDE          shift and go to state 7
    +
    +  ! TIMES           [ reduce using rule 2 ]
    +  ! DIVIDE          [ reduce using rule 2 ]
    +  ! PLUS            [ shift and go to state 6 ]
    +  ! MINUS           [ shift and go to state 5 ]
    +
    +state 11
    +
    +    expression -> expression PLUS expression .
    +    expression -> expression . PLUS expression
    +    expression -> expression . MINUS expression
    +    expression -> expression . TIMES expression
    +    expression -> expression . DIVIDE expression
    +
    +    $               reduce using rule 1
    +    PLUS            reduce using rule 1
    +    MINUS           reduce using rule 1
    +    RPAREN          reduce using rule 1
    +    TIMES           shift and go to state 4
    +    DIVIDE          shift and go to state 7
    +
    +  ! TIMES           [ reduce using rule 1 ]
    +  ! DIVIDE          [ reduce using rule 1 ]
    +  ! PLUS            [ shift and go to state 6 ]
    +  ! MINUS           [ shift and go to state 5 ]
    +
    +state 12
    +
    +    expression -> expression DIVIDE expression .
    +    expression -> expression . PLUS expression
    +    expression -> expression . MINUS expression
    +    expression -> expression . TIMES expression
    +    expression -> expression . DIVIDE expression
    +
    +    $               reduce using rule 4
    +    PLUS            reduce using rule 4
    +    MINUS           reduce using rule 4
    +    TIMES           reduce using rule 4
    +    DIVIDE          reduce using rule 4
    +    RPAREN          reduce using rule 4
    +
    +  ! PLUS            [ shift and go to state 6 ]
    +  ! MINUS           [ shift and go to state 5 ]
    +  ! TIMES           [ shift and go to state 4 ]
    +  ! DIVIDE          [ shift and go to state 7 ]
    +
    +state 13
    +
    +    expression -> LPAREN expression RPAREN .
    +
    +    $               reduce using rule 6
    +    PLUS            reduce using rule 6
    +    MINUS           reduce using rule 6
    +    TIMES           reduce using rule 6
    +    DIVIDE          reduce using rule 6
    +    RPAREN          reduce using rule 6
    +
    +
    + +The different states that appear in this file are a representation of +every possible sequence of valid input tokens allowed by the grammar. +When receiving input tokens, the parser is building up a stack and +looking for matching rules. Each state keeps track of the grammar +rules that might be in the process of being matched at that point. Within each +rule, the "." character indicates the current location of the parse +within that rule. In addition, the actions for each valid input token +are listed. When a shift/reduce or reduce/reduce conflict arises, +rules not selected are prefixed with an !. For example: + +
    +
    +  ! TIMES           [ reduce using rule 2 ]
    +  ! DIVIDE          [ reduce using rule 2 ]
    +  ! PLUS            [ shift and go to state 6 ]
    +  ! MINUS           [ shift and go to state 5 ]
    +
    +
    + +By looking at these rules (and with a little practice), you can usually track down the source +of most parsing conflicts. It should also be stressed that not all shift-reduce conflicts are +bad. However, the only way to be sure that they are resolved correctly is to look at parser.out. + +

    6.8 Syntax Error Handling

    + + +If you are creating a parser for production use, the handling of +syntax errors is important. As a general rule, you don't want a +parser to simply throw up its hands and stop at the first sign of +trouble. Instead, you want it to report the error, recover if possible, and +continue parsing so that all of the errors in the input get reported +to the user at once. This is the standard behavior found in compilers +for languages such as C, C++, and Java. + +In PLY, when a syntax error occurs during parsing, the error is immediately +detected (i.e., the parser does not read any more tokens beyond the +source of the error). However, at this point, the parser enters a +recovery mode that can be used to try and continue further parsing. +As a general rule, error recovery in LR parsers is a delicate +topic that involves ancient rituals and black-magic. The recovery mechanism +provided by yacc.py is comparable to Unix yacc so you may want +consult a book like O'Reilly's "Lex and Yacc" for some of the finer details. + +

    +When a syntax error occurs, yacc.py performs the following steps: + +

      +
    1. On the first occurrence of an error, the user-defined p_error() function +is called with the offending token as an argument. However, if the syntax error is due to +reaching the end-of-file, p_error() is called with an argument of None. +Afterwards, the parser enters +an "error-recovery" mode in which it will not make future calls to p_error() until it +has successfully shifted at least 3 tokens onto the parsing stack. + +

      +

    2. If no recovery action is taken in p_error(), the offending lookahead token is replaced +with a special error token. + +

      +

    3. If the offending lookahead token is already set to error, the top item of the parsing stack is +deleted. + +

      +

    4. If the entire parsing stack is unwound, the parser enters a restart state and attempts to start +parsing from its initial state. + +

      +

    5. If a grammar rule accepts error as a token, it will be +shifted onto the parsing stack. + +

      +

    6. If the top item of the parsing stack is error, lookahead tokens will be discarded until the +parser can successfully shift a new symbol or reduce a rule involving error. +
    + +

    6.8.1 Recovery and resynchronization with error rules

    + + +The most well-behaved approach for handling syntax errors is to write grammar rules that include the error +token. For example, suppose your language had a grammar rule for a print statement like this: + +
    +
    +def p_statement_print(p):
    +     'statement : PRINT expr SEMI'
    +     ...
    +
    +
    + +To account for the possibility of a bad expression, you might write an additional grammar rule like this: + +
    +
    +def p_statement_print_error(p):
    +     'statement : PRINT error SEMI'
    +     print "Syntax error in print statement. Bad expression"
    +
    +
    +
    + +In this case, the error token will match any sequence of +tokens that might appear up to the first semicolon that is +encountered. Once the semicolon is reached, the rule will be +invoked and the error token will go away. + +

    +This type of recovery is sometimes known as parser resynchronization. +The error token acts as a wildcard for any bad input text and +the token immediately following error acts as a +synchronization token. + +

    +It is important to note that the error token usually does not appear as the last token +on the right in an error rule. For example: + +

    +
    +def p_statement_print_error(p):
    +    'statement : PRINT error'
    +    print "Syntax error in print statement. Bad expression"
    +
    +
    + +This is because the first bad token encountered will cause the rule to +be reduced--which may make it difficult to recover if more bad tokens +immediately follow. + +

    6.8.2 Panic mode recovery

    + + +An alternative error recovery scheme is to enter a panic mode recovery in which tokens are +discarded to a point where the parser might be able to recover in some sensible manner. + +

    +Panic mode recovery is implemented entirely in the p_error() function. For example, this +function starts discarding tokens until it reaches a closing '}'. Then, it restarts the +parser in its initial state. + +

    +
    +def p_error(p):
    +    print "Whoa. You are seriously hosed."
    +    # Read ahead looking for a closing '}'
    +    while 1:
    +        tok = yacc.token()             # Get the next token
    +        if not tok or tok.type == 'RBRACE': break
    +    yacc.restart()
    +
    +
    + +

    +This function simply discards the bad token and tells the parser that the error was ok. + +

    +
    +def p_error(p):
    +    print "Syntax error at token", p.type
    +    # Just discard the token and tell the parser it's okay.
    +    yacc.errok()
    +
    +
    + +

    +Within the p_error() function, three functions are available to control the behavior +of the parser: +

    +

      +
    • yacc.errok(). This resets the parser state so it doesn't think it's in error-recovery +mode. This will prevent an error token from being generated and will reset the internal +error counters so that the next syntax error will call p_error() again. + +

      +

    • yacc.token(). This returns the next token on the input stream. + +

      +

    • yacc.restart(). This discards the entire parsing stack and resets the parser +to its initial state. +
    + +Note: these functions are only available when invoking p_error() and are not available +at any other time. + +

    +To supply the next lookahead token to the parser, p_error() can return a token. This might be +useful if trying to synchronize on special characters. For example: + +

    +
    +def p_error(p):
    +    # Read ahead looking for a terminating ";"
    +    while 1:
    +        tok = yacc.token()             # Get the next token
    +        if not tok or tok.type == 'SEMI': break
    +    yacc.errok()
    +
    +    # Return SEMI to the parser as the next lookahead token
    +    return tok  
    +
    +
    + +

    6.8.3 Signaling an error from a production

    + + +If necessary, a production rule can manually force the parser to enter error recovery. This +is done by raising the SyntaxError exception like this: + +
    +
    +def p_production(p):
    +    'production : some production ...'
    +    raise SyntaxError
    +
    +
    + +The effect of raising SyntaxError is the same as if the last symbol shifted onto the +parsing stack was actually a syntax error. Thus, when you do this, the last symbol shifted is popped off +of the parsing stack and the current lookahead token is set to an error token. The parser +then enters error-recovery mode where it tries to reduce rules that can accept error tokens. +The steps that follow from this point are exactly the same as if a syntax error were detected and +p_error() were called. + +

    +One important aspect of manually setting an error is that the p_error() function will NOT be +called in this case. If you need to issue an error message, make sure you do it in the production that +raises SyntaxError. + +

    +Note: This feature of PLY is meant to mimic the behavior of the YYERROR macro in yacc. + + +

    6.8.4 General comments on error handling

    + + +For normal types of languages, error recovery with error rules and resynchronization characters is probably the most reliable +technique. This is because you can instrument the grammar to catch errors at selected places where it is relatively easy +to recover and continue parsing. Panic mode recovery is really only useful in certain specialized applications where you might want +to discard huge portions of the input text to find a valid restart point. + +

    6.9 Line Number and Position Tracking

    + + +Position tracking is often a tricky problem when writing compilers. +By default, PLY tracks the line number and position of all tokens. +This information is available using the following functions: + +
      +
    • p.lineno(num). Return the line number for symbol num +
    • p.lexpos(num). Return the lexing position for symbol num +
    + +For example: + +
    +
    +def p_expression(p):
    +    'expression : expression PLUS expression'
    +    line   = p.lineno(2)        # line number of the PLUS token
    +    index  = p.lexpos(2)        # Position of the PLUS token
    +
    +
    + +As an optional feature, yacc.py can automatically track line +numbers and positions for all of the grammar symbols as well. +However, this extra tracking requires extra processing and can +significantly slow down parsing. Therefore, it must be enabled by +passing the +tracking=True option to yacc.parse(). For example: + +
    +
    +yacc.parse(data,tracking=True)
    +
    +
    + +Once enabled, the lineno() and lexpos() methods work +for all grammar symbols. In addition, two additional methods can be +used: + +
      +
    • p.linespan(num). Return a tuple (startline,endline) with the starting and ending line number for symbol num. +
    • p.lexspan(num). Return a tuple (start,end) with the starting and ending positions for symbol num. +
    + +For example: + +
    +
    +def p_expression(p):
    +    'expression : expression PLUS expression'
    +    p.lineno(1)        # Line number of the left expression
    +    p.lineno(2)        # line number of the PLUS operator
    +    p.lineno(3)        # line number of the right expression
    +    ...
    +    start,end = p.linespan(3)    # Start,end lines of the right expression
    +    starti,endi = p.lexspan(3)   # Start,end positions of right expression
    +
    +
    +
    + +Note: The lexspan() function only returns the range of values up to the start of the last grammar symbol. + +

    +Although it may be convenient for PLY to track position information on +all grammar symbols, this is often unnecessary. For example, if you +are merely using line number information in an error message, you can +often just key off of a specific token in the grammar rule. For +example: + +

    +
    +def p_bad_func(p):
    +    'funccall : fname LPAREN error RPAREN'
    +    # Line number reported from LPAREN token
    +    print "Bad function call at line", p.lineno(2)
    +
    +
    + +

    +Similarly, you may get better parsing performance if you only +selectively propagate line number information where it's needed using +the p.set_lineno() method. For example: + +

    +
    +def p_fname(p):
    +    'fname : ID'
    +    p[0] = p[1]
    +    p.set_lineno(0,p.lineno(1))
    +
    +
    + +PLY doesn't retain line number information from rules that have already been +parsed. If you are building an abstract syntax tree and need to have line numbers, +you should make sure that the line numbers appear in the tree itself. + +

    6.10 AST Construction

    + + +yacc.py provides no special functions for constructing an +abstract syntax tree. However, such construction is easy enough to do +on your own. + +

    A minimal way to construct a tree is to simply create and +propagate a tuple or list in each grammar rule function. There +are many possible ways to do this, but one example would be something +like this: + +

    +
    +def p_expression_binop(p):
    +    '''expression : expression PLUS expression
    +                  | expression MINUS expression
    +                  | expression TIMES expression
    +                  | expression DIVIDE expression'''
    +
    +    p[0] = ('binary-expression',p[2],p[1],p[3])
    +
    +def p_expression_group(p):
    +    'expression : LPAREN expression RPAREN'
    +    p[0] = ('group-expression',p[2])
    +
    +def p_expression_number(p):
    +    'expression : NUMBER'
    +    p[0] = ('number-expression',p[1])
    +
    +
    + +

    +Another approach is to create a set of data structure for different +kinds of abstract syntax tree nodes and assign nodes to p[0] +in each rule. For example: + +

    +
    +class Expr: pass
    +
    +class BinOp(Expr):
    +    def __init__(self,left,op,right):
    +        self.type = "binop"
    +        self.left = left
    +        self.right = right
    +        self.op = op
    +
    +class Number(Expr):
    +    def __init__(self,value):
    +        self.type = "number"
    +        self.value = value
    +
    +def p_expression_binop(p):
    +    '''expression : expression PLUS expression
    +                  | expression MINUS expression
    +                  | expression TIMES expression
    +                  | expression DIVIDE expression'''
    +
    +    p[0] = BinOp(p[1],p[2],p[3])
    +
    +def p_expression_group(p):
    +    'expression : LPAREN expression RPAREN'
    +    p[0] = p[2]
    +
    +def p_expression_number(p):
    +    'expression : NUMBER'
    +    p[0] = Number(p[1])
    +
    +
    + +The advantage to this approach is that it may make it easier to attach more complicated +semantics, type checking, code generation, and other features to the node classes. + +

    +To simplify tree traversal, it may make sense to pick a very generic +tree structure for your parse tree nodes. For example: + +

    +
    +class Node:
    +    def __init__(self,type,children=None,leaf=None):
    +         self.type = type
    +         if children:
    +              self.children = children
    +         else:
    +              self.children = [ ]
    +         self.leaf = leaf
    +	 
    +def p_expression_binop(p):
    +    '''expression : expression PLUS expression
    +                  | expression MINUS expression
    +                  | expression TIMES expression
    +                  | expression DIVIDE expression'''
    +
    +    p[0] = Node("binop", [p[1],p[3]], p[2])
    +
    +
    + +

    6.11 Embedded Actions

    + + +The parsing technique used by yacc only allows actions to be executed at the end of a rule. For example, +suppose you have a rule like this: + +
    +
    +def p_foo(p):
    +    "foo : A B C D"
    +    print "Parsed a foo", p[1],p[2],p[3],p[4]
    +
    +
    + +

    +In this case, the supplied action code only executes after all of the +symbols A, B, C, and D have been +parsed. Sometimes, however, it is useful to execute small code +fragments during intermediate stages of parsing. For example, suppose +you wanted to perform some action immediately after A has +been parsed. To do this, write an empty rule like this: + +

    +
    +def p_foo(p):
    +    "foo : A seen_A B C D"
    +    print "Parsed a foo", p[1],p[3],p[4],p[5]
    +    print "seen_A returned", p[2]
    +
    +def p_seen_A(p):
    +    "seen_A :"
    +    print "Saw an A = ", p[-1]   # Access grammar symbol to left
    +    p[0] = some_value            # Assign value to seen_A
    +
    +
    +
    + +

    +In this example, the empty seen_A rule executes immediately +after A is shifted onto the parsing stack. Within this +rule, p[-1] refers to the symbol on the stack that appears +immediately to the left of the seen_A symbol. In this case, +it would be the value of A in the foo rule +immediately above. Like other rules, a value can be returned from an +embedded action by simply assigning it to p[0] + +

    +The use of embedded actions can sometimes introduce extra shift/reduce conflicts. For example, +this grammar has no conflicts: + +

    +
    +def p_foo(p):
    +    """foo : abcd
    +           | abcx"""
    +
    +def p_abcd(p):
    +    "abcd : A B C D"
    +
    +def p_abcx(p):
    +    "abcx : A B C X"
    +
    +
    + +However, if you insert an embedded action into one of the rules like this, + +
    +
    +def p_foo(p):
    +    """foo : abcd
    +           | abcx"""
    +
    +def p_abcd(p):
    +    "abcd : A B C D"
    +
    +def p_abcx(p):
    +    "abcx : A B seen_AB C X"
    +
    +def p_seen_AB(p):
    +    "seen_AB :"
    +
    +
    + +an extra shift-reduce conflict will be introduced. This conflict is +caused by the fact that the same symbol C appears next in +both the abcd and abcx rules. The parser can either +shift the symbol (abcd rule) or reduce the empty +rule seen_AB (abcx rule). + +

    +A common use of embedded rules is to control other aspects of parsing +such as scoping of local variables. For example, if you were parsing C code, you might +write code like this: + +

    +
    +def p_statements_block(p):
    +    "statements: LBRACE new_scope statements RBRACE"""
    +    # Action code
    +    ...
    +    pop_scope()        # Return to previous scope
    +
    +def p_new_scope(p):
    +    "new_scope :"
    +    # Create a new scope for local variables
    +    s = new_scope()
    +    push_scope(s)
    +    ...
    +
    +
    + +In this case, the embedded action new_scope executes +immediately after a LBRACE ({) symbol is parsed. +This might adjust internal symbol tables and other aspects of the +parser. Upon completion of the rule statements_block, code +might undo the operations performed in the embedded action +(e.g., pop_scope()). + +

    6.12 Miscellaneous Yacc Notes

    + + +
      +
    • The default parsing method is LALR. To use SLR instead, run yacc() as follows: + +
      +
      +yacc.yacc(method="SLR")
      +
      +
      +Note: LALR table generation takes approximately twice as long as SLR table generation. There is no +difference in actual parsing performance---the same code is used in both cases. LALR is preferred when working +with more complicated grammars since it is more powerful. + +

      + +

    • By default, yacc.py relies on lex.py for tokenizing. However, an alternative tokenizer +can be supplied as follows: + +
      +
      +yacc.parse(lexer=x)
      +
      +
      +in this case, x must be a Lexer object that minimally has a x.token() method for retrieving the next +token. If an input string is given to yacc.parse(), the lexer must also have an x.input() method. + +

      +

    • By default, the yacc generates tables in debugging mode (which produces the parser.out file and other output). +To disable this, use + +
      +
      +yacc.yacc(debug=0)
      +
      +
      + +

      +

    • To change the name of the parsetab.py file, use: + +
      +
      +yacc.yacc(tabmodule="foo")
      +
      +
      + +

      +

    • To change the directory in which the parsetab.py file (and other output files) are written, use: +
      +
      +yacc.yacc(tabmodule="foo",outputdir="somedirectory")
      +
      +
      + +

      +

    • To prevent yacc from generating any kind of parser table file, use: +
      +
      +yacc.yacc(write_tables=0)
      +
      +
      + +Note: If you disable table generation, yacc() will regenerate the parsing tables +each time it runs (which may take awhile depending on how large your grammar is). + +

      +

    • To print copious amounts of debugging during parsing, use: + +
      +
      +yacc.parse(debug=1)     
      +
      +
      + +

      +

    • The yacc.yacc() function really returns a parser object. If you want to support multiple +parsers in the same application, do this: + +
      +
      +p = yacc.yacc()
      +...
      +p.parse()
      +
      +
      + +Note: The function yacc.parse() is bound to the last parser that was generated. + +

      +

    • Since the generation of the LALR tables is relatively expensive, previously generated tables are +cached and reused if possible. The decision to regenerate the tables is determined by taking an MD5 +checksum of all grammar rules and precedence rules. Only in the event of a mismatch are the tables regenerated. + +

      +It should be noted that table generation is reasonably efficient, even for grammars that involve around a 100 rules +and several hundred states. For more complex languages such as C, table generation may take 30-60 seconds on a slow +machine. Please be patient. + +

      +

    • Since LR parsing is driven by tables, the performance of the parser is largely independent of the +size of the grammar. The biggest bottlenecks will be the lexer and the complexity of the code in your grammar rules. +
    + +

    7. Multiple Parsers and Lexers

    + + +In advanced parsing applications, you may want to have multiple +parsers and lexers. + +

    +As a general rules this isn't a problem. However, to make it work, +you need to carefully make sure everything gets hooked up correctly. +First, make sure you save the objects returned by lex() and +yacc(). For example: + +

    +
    +lexer  = lex.lex()       # Return lexer object
    +parser = yacc.yacc()     # Return parser object
    +
    +
    + +Next, when parsing, make sure you give the parse() function a reference to the lexer it +should be using. For example: + +
    +
    +parser.parse(text,lexer=lexer)
    +
    +
    + +If you forget to do this, the parser will use the last lexer +created--which is not always what you want. + +

    +Within lexer and parser rule functions, these objects are also +available. In the lexer, the "lexer" attribute of a token refers to +the lexer object that triggered the rule. For example: + +

    +
    +def t_NUMBER(t):
    +   r'\d+'
    +   ...
    +   print t.lexer           # Show lexer object
    +
    +
    + +In the parser, the "lexer" and "parser" attributes refer to the lexer +and parser objects respectively. + +
    +
    +def p_expr_plus(p):
    +   'expr : expr PLUS expr'
    +   ...
    +   print p.parser          # Show parser object
    +   print p.lexer           # Show lexer object
    +
    +
    + +If necessary, arbitrary attributes can be attached to the lexer or parser object. +For example, if you wanted to have different parsing modes, you could attach a mode +attribute to the parser object and look at it later. + +

    8. Using Python's Optimized Mode

    + + +Because PLY uses information from doc-strings, parsing and lexing +information must be gathered while running the Python interpreter in +normal mode (i.e., not with the -O or -OO options). However, if you +specify optimized mode like this: + +
    +
    +lex.lex(optimize=1)
    +yacc.yacc(optimize=1)
    +
    +
    + +then PLY can later be used when Python runs in optimized mode. To make this work, +make sure you first run Python in normal mode. Once the lexing and parsing tables +have been generated the first time, run Python in optimized mode. PLY will use +the tables without the need for doc strings. + +

    +Beware: running PLY in optimized mode disables a lot of error +checking. You should only do this when your project has stabilized +and you don't need to do any debugging. One of the purposes of +optimized mode is to substantially decrease the startup time of +your compiler (by assuming that everything is already properly +specified and works). + +

    9. Advanced Debugging

    + + +

    +Debugging a compiler is typically not an easy task. PLY provides some +advanced diagonistic capabilities through the use of Python's +logging module. The next two sections describe this: + +

    9.1 Debugging the lex() and yacc() commands

    + + +

    +Both the lex() and yacc() commands have a debugging +mode that can be enabled using the debug flag. For example: + +

    +
    +lex.lex(debug=True)
    +yacc.yacc(debug=True)
    +
    +
    + +Normally, the output produced by debugging is routed to either +standard error or, in the case of yacc(), to a file +parser.out. This output can be more carefully controlled +by supplying a logging object. Here is an example that adds +information about where different debugging messages are coming from: + +
    +
    +# Set up a logging object
    +import logging
    +logging.basicConfig(
    +    level = logging.DEBUG,
    +    filename = "parselog.txt",
    +    filemode = "w",
    +    format = "%(filename)10s:%(lineno)4d:%(message)s"
    +)
    +log = logging.getLogger()
    +
    +lex.lex(debug=True,debuglog=log)
    +yacc.yacc(debug=True,debuglog=log)
    +
    +
    + +If you supply a custom logger, the amount of debugging +information produced can be controlled by setting the logging level. +Typically, debugging messages are either issued at the DEBUG, +INFO, or WARNING levels. + +

    +PLY's error messages and warnings are also produced using the logging +interface. This can be controlled by passing a logging object +using the errorlog parameter. + +

    +
    +lex.lex(errorlog=log)
    +yacc.yacc(errorlog=log)
    +
    +
    + +If you want to completely silence warnings, you can either pass in a +logging object with an appropriate filter level or use the NullLogger +object defined in either lex or yacc. For example: + +
    +
    +yacc.yacc(errorlog=yacc.NullLogger())
    +
    +
    + +

    9.2 Run-time Debugging

    + + +

    +To enable run-time debugging of a parser, use the debug option to parse. This +option can either be an integer (which simply turns debugging on or off) or an instance +of a logger object. For example: + +

    +
    +log = logging.getLogger()
    +parser.parse(input,debug=log)
    +
    +
    + +If a logging object is passed, you can use its filtering level to control how much +output gets generated. The INFO level is used to produce information +about rule reductions. The DEBUG level will show information about the +parsing stack, token shifts, and other details. The ERROR level shows information +related to parsing errors. + +

    +For very complicated problems, you should pass in a logging object that +redirects to a file where you can more easily inspect the output after +execution. + +

    10. Where to go from here?

    + + +The examples directory of the PLY distribution contains several simple examples. Please consult a +compilers textbook for the theory and underlying implementation details or LR parsing. + + + + + + + + + + diff --git a/simulators/gem5/ext/ply/example/BASIC/README b/simulators/gem5/ext/ply/example/BASIC/README new file mode 100644 index 00000000..be24a300 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/README @@ -0,0 +1,79 @@ +Inspired by a September 14, 2006 Salon article "Why Johnny Can't Code" by +David Brin (http://www.salon.com/tech/feature/2006/09/14/basic/index.html), +I thought that a fully working BASIC interpreter might be an interesting, +if not questionable, PLY example. Uh, okay, so maybe it's just a bad idea, +but in any case, here it is. + +In this example, you'll find a rough implementation of 1964 Dartmouth BASIC +as described in the manual at: + + http://www.bitsavers.org/pdf/dartmouth/BASIC_Oct64.pdf + +See also: + + http://en.wikipedia.org/wiki/Dartmouth_BASIC + +This dialect is downright primitive---there are no string variables +and no facilities for interactive input. Moreover, subroutines and functions +are brain-dead even more than they usually are for BASIC. Of course, +the GOTO statement is provided. + +Nevertheless, there are a few interesting aspects of this example: + + - It illustrates a fully working interpreter including lexing, parsing, + and interpretation of instructions. + + - The parser shows how to catch and report various kinds of parsing + errors in a more graceful way. + + - The example both parses files (supplied on command line) and + interactive input entered line by line. + + - It shows how you might represent parsed information. In this case, + each BASIC statement is encoded into a Python tuple containing the + statement type and parameters. These tuples are then stored in + a dictionary indexed by program line numbers. + + - Even though it's just BASIC, the parser contains more than 80 + rules and 150 parsing states. Thus, it's a little more meaty than + the calculator example. + +To use the example, run it as follows: + + % python basic.py hello.bas + HELLO WORLD + % + +or use it interactively: + + % python basic.py + [BASIC] 10 PRINT "HELLO WORLD" + [BASIC] 20 END + [BASIC] RUN + HELLO WORLD + [BASIC] + +The following files are defined: + + basic.py - High level script that controls everything + basiclex.py - BASIC tokenizer + basparse.py - BASIC parser + basinterp.py - BASIC interpreter that runs parsed programs. + +In addition, a number of sample BASIC programs (.bas suffix) are +provided. These were taken out of the Dartmouth manual. + +Disclaimer: I haven't spent a ton of time testing this and it's likely that +I've skimped here and there on a few finer details (e.g., strictly enforcing +variable naming rules). However, the interpreter seems to be able to run +the examples in the BASIC manual. + +Have fun! + +-Dave + + + + + + diff --git a/simulators/gem5/ext/ply/example/BASIC/basic.py b/simulators/gem5/ext/ply/example/BASIC/basic.py new file mode 100644 index 00000000..b14483d2 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/basic.py @@ -0,0 +1,71 @@ +# An implementation of Dartmouth BASIC (1964) +# + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +import basiclex +import basparse +import basinterp + +# If a filename has been specified, we try to run it. +# If a runtime error occurs, we bail out and enter +# interactive mode below +if len(sys.argv) == 2: + data = open(sys.argv[1]).read() + prog = basparse.parse(data) + if not prog: raise SystemExit + b = basinterp.BasicInterpreter(prog) + try: + b.run() + raise SystemExit + except RuntimeError: + pass + +else: + b = basinterp.BasicInterpreter({}) + +# Interactive mode. This incrementally adds/deletes statements +# from the program stored in the BasicInterpreter object. In +# addition, special commands 'NEW','LIST',and 'RUN' are added. +# Specifying a line number with no code deletes that line from +# the program. + +while 1: + try: + line = raw_input("[BASIC] ") + except EOFError: + raise SystemExit + if not line: continue + line += "\n" + prog = basparse.parse(line) + if not prog: continue + + keys = list(prog) + if keys[0] > 0: + b.add_statements(prog) + else: + stat = prog[keys[0]] + if stat[0] == 'RUN': + try: + b.run() + except RuntimeError: + pass + elif stat[0] == 'LIST': + b.list() + elif stat[0] == 'BLANK': + b.del_line(stat[1]) + elif stat[0] == 'NEW': + b.new() + + + + + + + + + diff --git a/simulators/gem5/ext/ply/example/BASIC/basiclex.py b/simulators/gem5/ext/ply/example/BASIC/basiclex.py new file mode 100644 index 00000000..3d27cdee --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/basiclex.py @@ -0,0 +1,74 @@ +# An implementation of Dartmouth BASIC (1964) + +from ply import * + +keywords = ( + 'LET','READ','DATA','PRINT','GOTO','IF','THEN','FOR','NEXT','TO','STEP', + 'END','STOP','DEF','GOSUB','DIM','REM','RETURN','RUN','LIST','NEW', +) + +tokens = keywords + ( + 'EQUALS','PLUS','MINUS','TIMES','DIVIDE','POWER', + 'LPAREN','RPAREN','LT','LE','GT','GE','NE', + 'COMMA','SEMI', 'INTEGER','FLOAT', 'STRING', + 'ID','NEWLINE' +) + +t_ignore = ' \t' + +def t_REM(t): + r'REM .*' + return t + +def t_ID(t): + r'[A-Z][A-Z0-9]*' + if t.value in keywords: + t.type = t.value + return t + +t_EQUALS = r'=' +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_POWER = r'\^' +t_DIVIDE = r'/' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_LT = r'<' +t_LE = r'<=' +t_GT = r'>' +t_GE = r'>=' +t_NE = r'<>' +t_COMMA = r'\,' +t_SEMI = r';' +t_INTEGER = r'\d+' +t_FLOAT = r'((\d*\.\d+)(E[\+-]?\d+)?|([1-9]\d*E[\+-]?\d+))' +t_STRING = r'\".*?\"' + +def t_NEWLINE(t): + r'\n' + t.lexer.lineno += 1 + return t + +def t_error(t): + print("Illegal character %s" % t.value[0]) + t.lexer.skip(1) + +lex.lex(debug=0) + + + + + + + + + + + + + + + + + diff --git a/simulators/gem5/ext/ply/example/BASIC/basiclog.py b/simulators/gem5/ext/ply/example/BASIC/basiclog.py new file mode 100644 index 00000000..ccfd7b96 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/basiclog.py @@ -0,0 +1,79 @@ +# An implementation of Dartmouth BASIC (1964) +# + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +import logging +logging.basicConfig( + level = logging.INFO, + filename = "parselog.txt", + filemode = "w" +) +log = logging.getLogger() + +import basiclex +import basparse +import basinterp + +# If a filename has been specified, we try to run it. +# If a runtime error occurs, we bail out and enter +# interactive mode below +if len(sys.argv) == 2: + data = open(sys.argv[1]).read() + prog = basparse.parse(data,debug=log) + if not prog: raise SystemExit + b = basinterp.BasicInterpreter(prog) + try: + b.run() + raise SystemExit + except RuntimeError: + pass + +else: + b = basinterp.BasicInterpreter({}) + +# Interactive mode. This incrementally adds/deletes statements +# from the program stored in the BasicInterpreter object. In +# addition, special commands 'NEW','LIST',and 'RUN' are added. +# Specifying a line number with no code deletes that line from +# the program. + +while 1: + try: + line = raw_input("[BASIC] ") + except EOFError: + raise SystemExit + if not line: continue + line += "\n" + prog = basparse.parse(line,debug=log) + if not prog: continue + + keys = list(prog) + if keys[0] > 0: + b.add_statements(prog) + else: + stat = prog[keys[0]] + if stat[0] == 'RUN': + try: + b.run() + except RuntimeError: + pass + elif stat[0] == 'LIST': + b.list() + elif stat[0] == 'BLANK': + b.del_line(stat[1]) + elif stat[0] == 'NEW': + b.new() + + + + + + + + + diff --git a/simulators/gem5/ext/ply/example/BASIC/basinterp.py b/simulators/gem5/ext/ply/example/BASIC/basinterp.py new file mode 100644 index 00000000..3e8a7774 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/basinterp.py @@ -0,0 +1,441 @@ +# This file provides the runtime support for running a basic program +# Assumes the program has been parsed using basparse.py + +import sys +import math +import random + +class BasicInterpreter: + + # Initialize the interpreter. prog is a dictionary + # containing (line,statement) mappings + def __init__(self,prog): + self.prog = prog + + self.functions = { # Built-in function table + 'SIN' : lambda z: math.sin(self.eval(z)), + 'COS' : lambda z: math.cos(self.eval(z)), + 'TAN' : lambda z: math.tan(self.eval(z)), + 'ATN' : lambda z: math.atan(self.eval(z)), + 'EXP' : lambda z: math.exp(self.eval(z)), + 'ABS' : lambda z: abs(self.eval(z)), + 'LOG' : lambda z: math.log(self.eval(z)), + 'SQR' : lambda z: math.sqrt(self.eval(z)), + 'INT' : lambda z: int(self.eval(z)), + 'RND' : lambda z: random.random() + } + + # Collect all data statements + def collect_data(self): + self.data = [] + for lineno in self.stat: + if self.prog[lineno][0] == 'DATA': + self.data = self.data + self.prog[lineno][1] + self.dc = 0 # Initialize the data counter + + # Check for end statements + def check_end(self): + has_end = 0 + for lineno in self.stat: + if self.prog[lineno][0] == 'END' and not has_end: + has_end = lineno + if not has_end: + print("NO END INSTRUCTION") + self.error = 1 + return + if has_end != lineno: + print("END IS NOT LAST") + self.error = 1 + + # Check loops + def check_loops(self): + for pc in range(len(self.stat)): + lineno = self.stat[pc] + if self.prog[lineno][0] == 'FOR': + forinst = self.prog[lineno] + loopvar = forinst[1] + for i in range(pc+1,len(self.stat)): + if self.prog[self.stat[i]][0] == 'NEXT': + nextvar = self.prog[self.stat[i]][1] + if nextvar != loopvar: continue + self.loopend[pc] = i + break + else: + print("FOR WITHOUT NEXT AT LINE %s" % self.stat[pc]) + self.error = 1 + + # Evaluate an expression + def eval(self,expr): + etype = expr[0] + if etype == 'NUM': return expr[1] + elif etype == 'GROUP': return self.eval(expr[1]) + elif etype == 'UNARY': + if expr[1] == '-': return -self.eval(expr[2]) + elif etype == 'BINOP': + if expr[1] == '+': return self.eval(expr[2])+self.eval(expr[3]) + elif expr[1] == '-': return self.eval(expr[2])-self.eval(expr[3]) + elif expr[1] == '*': return self.eval(expr[2])*self.eval(expr[3]) + elif expr[1] == '/': return float(self.eval(expr[2]))/self.eval(expr[3]) + elif expr[1] == '^': return abs(self.eval(expr[2]))**self.eval(expr[3]) + elif etype == 'VAR': + var,dim1,dim2 = expr[1] + if not dim1 and not dim2: + if var in self.vars: + return self.vars[var] + else: + print("UNDEFINED VARIABLE %s AT LINE %s" % (var, self.stat[self.pc])) + raise RuntimeError + # May be a list lookup or a function evaluation + if dim1 and not dim2: + if var in self.functions: + # A function + return self.functions[var](dim1) + else: + # A list evaluation + if var in self.lists: + dim1val = self.eval(dim1) + if dim1val < 1 or dim1val > len(self.lists[var]): + print("LIST INDEX OUT OF BOUNDS AT LINE %s" % self.stat[self.pc]) + raise RuntimeError + return self.lists[var][dim1val-1] + if dim1 and dim2: + if var in self.tables: + dim1val = self.eval(dim1) + dim2val = self.eval(dim2) + if dim1val < 1 or dim1val > len(self.tables[var]) or dim2val < 1 or dim2val > len(self.tables[var][0]): + print("TABLE INDEX OUT OUT BOUNDS AT LINE %s" % self.stat[self.pc]) + raise RuntimeError + return self.tables[var][dim1val-1][dim2val-1] + print("UNDEFINED VARIABLE %s AT LINE %s" % (var, self.stat[self.pc])) + raise RuntimeError + + # Evaluate a relational expression + def releval(self,expr): + etype = expr[1] + lhs = self.eval(expr[2]) + rhs = self.eval(expr[3]) + if etype == '<': + if lhs < rhs: return 1 + else: return 0 + + elif etype == '<=': + if lhs <= rhs: return 1 + else: return 0 + + elif etype == '>': + if lhs > rhs: return 1 + else: return 0 + + elif etype == '>=': + if lhs >= rhs: return 1 + else: return 0 + + elif etype == '=': + if lhs == rhs: return 1 + else: return 0 + + elif etype == '<>': + if lhs != rhs: return 1 + else: return 0 + + # Assignment + def assign(self,target,value): + var, dim1, dim2 = target + if not dim1 and not dim2: + self.vars[var] = self.eval(value) + elif dim1 and not dim2: + # List assignment + dim1val = self.eval(dim1) + if not var in self.lists: + self.lists[var] = [0]*10 + + if dim1val > len(self.lists[var]): + print ("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc]) + raise RuntimeError + self.lists[var][dim1val-1] = self.eval(value) + elif dim1 and dim2: + dim1val = self.eval(dim1) + dim2val = self.eval(dim2) + if not var in self.tables: + temp = [0]*10 + v = [] + for i in range(10): v.append(temp[:]) + self.tables[var] = v + # Variable already exists + if dim1val > len(self.tables[var]) or dim2val > len(self.tables[var][0]): + print("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc]) + raise RuntimeError + self.tables[var][dim1val-1][dim2val-1] = self.eval(value) + + # Change the current line number + def goto(self,linenum): + if not linenum in self.prog: + print("UNDEFINED LINE NUMBER %d AT LINE %d" % (linenum, self.stat[self.pc])) + raise RuntimeError + self.pc = self.stat.index(linenum) + + # Run it + def run(self): + self.vars = { } # All variables + self.lists = { } # List variables + self.tables = { } # Tables + self.loops = [ ] # Currently active loops + self.loopend= { } # Mapping saying where loops end + self.gosub = None # Gosub return point (if any) + self.error = 0 # Indicates program error + + self.stat = list(self.prog) # Ordered list of all line numbers + self.stat.sort() + self.pc = 0 # Current program counter + + # Processing prior to running + + self.collect_data() # Collect all of the data statements + self.check_end() + self.check_loops() + + if self.error: raise RuntimeError + + while 1: + line = self.stat[self.pc] + instr = self.prog[line] + + op = instr[0] + + # END and STOP statements + if op == 'END' or op == 'STOP': + break # We're done + + # GOTO statement + elif op == 'GOTO': + newline = instr[1] + self.goto(newline) + continue + + # PRINT statement + elif op == 'PRINT': + plist = instr[1] + out = "" + for label,val in plist: + if out: + out += ' '*(15 - (len(out) % 15)) + out += label + if val: + if label: out += " " + eval = self.eval(val) + out += str(eval) + sys.stdout.write(out) + end = instr[2] + if not (end == ',' or end == ';'): + sys.stdout.write("\n") + if end == ',': sys.stdout.write(" "*(15-(len(out) % 15))) + if end == ';': sys.stdout.write(" "*(3-(len(out) % 3))) + + # LET statement + elif op == 'LET': + target = instr[1] + value = instr[2] + self.assign(target,value) + + # READ statement + elif op == 'READ': + for target in instr[1]: + if self.dc < len(self.data): + value = ('NUM',self.data[self.dc]) + self.assign(target,value) + self.dc += 1 + else: + # No more data. Program ends + return + elif op == 'IF': + relop = instr[1] + newline = instr[2] + if (self.releval(relop)): + self.goto(newline) + continue + + elif op == 'FOR': + loopvar = instr[1] + initval = instr[2] + finval = instr[3] + stepval = instr[4] + + # Check to see if this is a new loop + if not self.loops or self.loops[-1][0] != self.pc: + # Looks like a new loop. Make the initial assignment + newvalue = initval + self.assign((loopvar,None,None),initval) + if not stepval: stepval = ('NUM',1) + stepval = self.eval(stepval) # Evaluate step here + self.loops.append((self.pc,stepval)) + else: + # It's a repeat of the previous loop + # Update the value of the loop variable according to the step + stepval = ('NUM',self.loops[-1][1]) + newvalue = ('BINOP','+',('VAR',(loopvar,None,None)),stepval) + + if self.loops[-1][1] < 0: relop = '>=' + else: relop = '<=' + if not self.releval(('RELOP',relop,newvalue,finval)): + # Loop is done. Jump to the NEXT + self.pc = self.loopend[self.pc] + self.loops.pop() + else: + self.assign((loopvar,None,None),newvalue) + + elif op == 'NEXT': + if not self.loops: + print("NEXT WITHOUT FOR AT LINE %s" % line) + return + + nextvar = instr[1] + self.pc = self.loops[-1][0] + loopinst = self.prog[self.stat[self.pc]] + forvar = loopinst[1] + if nextvar != forvar: + print("NEXT DOESN'T MATCH FOR AT LINE %s" % line) + return + continue + elif op == 'GOSUB': + newline = instr[1] + if self.gosub: + print("ALREADY IN A SUBROUTINE AT LINE %s" % line) + return + self.gosub = self.stat[self.pc] + self.goto(newline) + continue + + elif op == 'RETURN': + if not self.gosub: + print("RETURN WITHOUT A GOSUB AT LINE %s" % line) + return + self.goto(self.gosub) + self.gosub = None + + elif op == 'FUNC': + fname = instr[1] + pname = instr[2] + expr = instr[3] + def eval_func(pvalue,name=pname,self=self,expr=expr): + self.assign((pname,None,None),pvalue) + return self.eval(expr) + self.functions[fname] = eval_func + + elif op == 'DIM': + for vname,x,y in instr[1]: + if y == 0: + # Single dimension variable + self.lists[vname] = [0]*x + else: + # Double dimension variable + temp = [0]*y + v = [] + for i in range(x): + v.append(temp[:]) + self.tables[vname] = v + + self.pc += 1 + + # Utility functions for program listing + def expr_str(self,expr): + etype = expr[0] + if etype == 'NUM': return str(expr[1]) + elif etype == 'GROUP': return "(%s)" % self.expr_str(expr[1]) + elif etype == 'UNARY': + if expr[1] == '-': return "-"+str(expr[2]) + elif etype == 'BINOP': + return "%s %s %s" % (self.expr_str(expr[2]),expr[1],self.expr_str(expr[3])) + elif etype == 'VAR': + return self.var_str(expr[1]) + + def relexpr_str(self,expr): + return "%s %s %s" % (self.expr_str(expr[2]),expr[1],self.expr_str(expr[3])) + + def var_str(self,var): + varname,dim1,dim2 = var + if not dim1 and not dim2: return varname + if dim1 and not dim2: return "%s(%s)" % (varname, self.expr_str(dim1)) + return "%s(%s,%s)" % (varname, self.expr_str(dim1),self.expr_str(dim2)) + + # Create a program listing + def list(self): + stat = list(self.prog) # Ordered list of all line numbers + stat.sort() + for line in stat: + instr = self.prog[line] + op = instr[0] + if op in ['END','STOP','RETURN']: + print("%s %s" % (line, op)) + continue + elif op == 'REM': + print("%s %s" % (line, instr[1])) + elif op == 'PRINT': + _out = "%s %s " % (line, op) + first = 1 + for p in instr[1]: + if not first: _out += ", " + if p[0] and p[1]: _out += '"%s"%s' % (p[0],self.expr_str(p[1])) + elif p[1]: _out += self.expr_str(p[1]) + else: _out += '"%s"' % (p[0],) + first = 0 + if instr[2]: _out += instr[2] + print(_out) + elif op == 'LET': + print("%s LET %s = %s" % (line,self.var_str(instr[1]),self.expr_str(instr[2]))) + elif op == 'READ': + _out = "%s READ " % line + first = 1 + for r in instr[1]: + if not first: _out += "," + _out += self.var_str(r) + first = 0 + print(_out) + elif op == 'IF': + print("%s IF %s THEN %d" % (line,self.relexpr_str(instr[1]),instr[2])) + elif op == 'GOTO' or op == 'GOSUB': + print("%s %s %s" % (line, op, instr[1])) + elif op == 'FOR': + _out = "%s FOR %s = %s TO %s" % (line,instr[1],self.expr_str(instr[2]),self.expr_str(instr[3])) + if instr[4]: _out += " STEP %s" % (self.expr_str(instr[4])) + print(_out) + elif op == 'NEXT': + print("%s NEXT %s" % (line, instr[1])) + elif op == 'FUNC': + print("%s DEF %s(%s) = %s" % (line,instr[1],instr[2],self.expr_str(instr[3]))) + elif op == 'DIM': + _out = "%s DIM " % line + first = 1 + for vname,x,y in instr[1]: + if not first: _out += "," + first = 0 + if y == 0: + _out += "%s(%d)" % (vname,x) + else: + _out += "%s(%d,%d)" % (vname,x,y) + + print(_out) + elif op == 'DATA': + _out = "%s DATA " % line + first = 1 + for v in instr[1]: + if not first: _out += "," + first = 0 + _out += v + print(_out) + + # Erase the current program + def new(self): + self.prog = {} + + # Insert statements + def add_statements(self,prog): + for line,stat in prog.items(): + self.prog[line] = stat + + # Delete a statement + def del_line(self,lineno): + try: + del self.prog[lineno] + except KeyError: + pass + diff --git a/simulators/gem5/ext/ply/example/BASIC/basparse.py b/simulators/gem5/ext/ply/example/BASIC/basparse.py new file mode 100644 index 00000000..ccdeb16b --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/basparse.py @@ -0,0 +1,424 @@ +# An implementation of Dartmouth BASIC (1964) +# + +from ply import * +import basiclex + +tokens = basiclex.tokens + +precedence = ( + ('left', 'PLUS','MINUS'), + ('left', 'TIMES','DIVIDE'), + ('left', 'POWER'), + ('right','UMINUS') +) + +#### A BASIC program is a series of statements. We represent the program as a +#### dictionary of tuples indexed by line number. + +def p_program(p): + '''program : program statement + | statement''' + + if len(p) == 2 and p[1]: + p[0] = { } + line,stat = p[1] + p[0][line] = stat + elif len(p) ==3: + p[0] = p[1] + if not p[0]: p[0] = { } + if p[2]: + line,stat = p[2] + p[0][line] = stat + +#### This catch-all rule is used for any catastrophic errors. In this case, +#### we simply return nothing + +def p_program_error(p): + '''program : error''' + p[0] = None + p.parser.error = 1 + +#### Format of all BASIC statements. + +def p_statement(p): + '''statement : INTEGER command NEWLINE''' + if isinstance(p[2],str): + print("%s %s %s" % (p[2],"AT LINE", p[1])) + p[0] = None + p.parser.error = 1 + else: + lineno = int(p[1]) + p[0] = (lineno,p[2]) + +#### Interactive statements. + +def p_statement_interactive(p): + '''statement : RUN NEWLINE + | LIST NEWLINE + | NEW NEWLINE''' + p[0] = (0, (p[1],0)) + +#### Blank line number +def p_statement_blank(p): + '''statement : INTEGER NEWLINE''' + p[0] = (0,('BLANK',int(p[1]))) + +#### Error handling for malformed statements + +def p_statement_bad(p): + '''statement : INTEGER error NEWLINE''' + print("MALFORMED STATEMENT AT LINE %s" % p[1]) + p[0] = None + p.parser.error = 1 + +#### Blank line + +def p_statement_newline(p): + '''statement : NEWLINE''' + p[0] = None + +#### LET statement + +def p_command_let(p): + '''command : LET variable EQUALS expr''' + p[0] = ('LET',p[2],p[4]) + +def p_command_let_bad(p): + '''command : LET variable EQUALS error''' + p[0] = "BAD EXPRESSION IN LET" + +#### READ statement + +def p_command_read(p): + '''command : READ varlist''' + p[0] = ('READ',p[2]) + +def p_command_read_bad(p): + '''command : READ error''' + p[0] = "MALFORMED VARIABLE LIST IN READ" + +#### DATA statement + +def p_command_data(p): + '''command : DATA numlist''' + p[0] = ('DATA',p[2]) + +def p_command_data_bad(p): + '''command : DATA error''' + p[0] = "MALFORMED NUMBER LIST IN DATA" + +#### PRINT statement + +def p_command_print(p): + '''command : PRINT plist optend''' + p[0] = ('PRINT',p[2],p[3]) + +def p_command_print_bad(p): + '''command : PRINT error''' + p[0] = "MALFORMED PRINT STATEMENT" + +#### Optional ending on PRINT. Either a comma (,) or semicolon (;) + +def p_optend(p): + '''optend : COMMA + | SEMI + |''' + if len(p) == 2: + p[0] = p[1] + else: + p[0] = None + +#### PRINT statement with no arguments + +def p_command_print_empty(p): + '''command : PRINT''' + p[0] = ('PRINT',[],None) + +#### GOTO statement + +def p_command_goto(p): + '''command : GOTO INTEGER''' + p[0] = ('GOTO',int(p[2])) + +def p_command_goto_bad(p): + '''command : GOTO error''' + p[0] = "INVALID LINE NUMBER IN GOTO" + +#### IF-THEN statement + +def p_command_if(p): + '''command : IF relexpr THEN INTEGER''' + p[0] = ('IF',p[2],int(p[4])) + +def p_command_if_bad(p): + '''command : IF error THEN INTEGER''' + p[0] = "BAD RELATIONAL EXPRESSION" + +def p_command_if_bad2(p): + '''command : IF relexpr THEN error''' + p[0] = "INVALID LINE NUMBER IN THEN" + +#### FOR statement + +def p_command_for(p): + '''command : FOR ID EQUALS expr TO expr optstep''' + p[0] = ('FOR',p[2],p[4],p[6],p[7]) + +def p_command_for_bad_initial(p): + '''command : FOR ID EQUALS error TO expr optstep''' + p[0] = "BAD INITIAL VALUE IN FOR STATEMENT" + +def p_command_for_bad_final(p): + '''command : FOR ID EQUALS expr TO error optstep''' + p[0] = "BAD FINAL VALUE IN FOR STATEMENT" + +def p_command_for_bad_step(p): + '''command : FOR ID EQUALS expr TO expr STEP error''' + p[0] = "MALFORMED STEP IN FOR STATEMENT" + +#### Optional STEP qualifier on FOR statement + +def p_optstep(p): + '''optstep : STEP expr + | empty''' + if len(p) == 3: + p[0] = p[2] + else: + p[0] = None + +#### NEXT statement + +def p_command_next(p): + '''command : NEXT ID''' + + p[0] = ('NEXT',p[2]) + +def p_command_next_bad(p): + '''command : NEXT error''' + p[0] = "MALFORMED NEXT" + +#### END statement + +def p_command_end(p): + '''command : END''' + p[0] = ('END',) + +#### REM statement + +def p_command_rem(p): + '''command : REM''' + p[0] = ('REM',p[1]) + +#### STOP statement + +def p_command_stop(p): + '''command : STOP''' + p[0] = ('STOP',) + +#### DEF statement + +def p_command_def(p): + '''command : DEF ID LPAREN ID RPAREN EQUALS expr''' + p[0] = ('FUNC',p[2],p[4],p[7]) + +def p_command_def_bad_rhs(p): + '''command : DEF ID LPAREN ID RPAREN EQUALS error''' + p[0] = "BAD EXPRESSION IN DEF STATEMENT" + +def p_command_def_bad_arg(p): + '''command : DEF ID LPAREN error RPAREN EQUALS expr''' + p[0] = "BAD ARGUMENT IN DEF STATEMENT" + +#### GOSUB statement + +def p_command_gosub(p): + '''command : GOSUB INTEGER''' + p[0] = ('GOSUB',int(p[2])) + +def p_command_gosub_bad(p): + '''command : GOSUB error''' + p[0] = "INVALID LINE NUMBER IN GOSUB" + +#### RETURN statement + +def p_command_return(p): + '''command : RETURN''' + p[0] = ('RETURN',) + +#### DIM statement + +def p_command_dim(p): + '''command : DIM dimlist''' + p[0] = ('DIM',p[2]) + +def p_command_dim_bad(p): + '''command : DIM error''' + p[0] = "MALFORMED VARIABLE LIST IN DIM" + +#### List of variables supplied to DIM statement + +def p_dimlist(p): + '''dimlist : dimlist COMMA dimitem + | dimitem''' + if len(p) == 4: + p[0] = p[1] + p[0].append(p[3]) + else: + p[0] = [p[1]] + +#### DIM items + +def p_dimitem_single(p): + '''dimitem : ID LPAREN INTEGER RPAREN''' + p[0] = (p[1],eval(p[3]),0) + +def p_dimitem_double(p): + '''dimitem : ID LPAREN INTEGER COMMA INTEGER RPAREN''' + p[0] = (p[1],eval(p[3]),eval(p[5])) + +#### Arithmetic expressions + +def p_expr_binary(p): + '''expr : expr PLUS expr + | expr MINUS expr + | expr TIMES expr + | expr DIVIDE expr + | expr POWER expr''' + + p[0] = ('BINOP',p[2],p[1],p[3]) + +def p_expr_number(p): + '''expr : INTEGER + | FLOAT''' + p[0] = ('NUM',eval(p[1])) + +def p_expr_variable(p): + '''expr : variable''' + p[0] = ('VAR',p[1]) + +def p_expr_group(p): + '''expr : LPAREN expr RPAREN''' + p[0] = ('GROUP',p[2]) + +def p_expr_unary(p): + '''expr : MINUS expr %prec UMINUS''' + p[0] = ('UNARY','-',p[2]) + +#### Relational expressions + +def p_relexpr(p): + '''relexpr : expr LT expr + | expr LE expr + | expr GT expr + | expr GE expr + | expr EQUALS expr + | expr NE expr''' + p[0] = ('RELOP',p[2],p[1],p[3]) + +#### Variables + +def p_variable(p): + '''variable : ID + | ID LPAREN expr RPAREN + | ID LPAREN expr COMMA expr RPAREN''' + if len(p) == 2: + p[0] = (p[1],None,None) + elif len(p) == 5: + p[0] = (p[1],p[3],None) + else: + p[0] = (p[1],p[3],p[5]) + +#### Builds a list of variable targets as a Python list + +def p_varlist(p): + '''varlist : varlist COMMA variable + | variable''' + if len(p) > 2: + p[0] = p[1] + p[0].append(p[3]) + else: + p[0] = [p[1]] + + +#### Builds a list of numbers as a Python list + +def p_numlist(p): + '''numlist : numlist COMMA number + | number''' + + if len(p) > 2: + p[0] = p[1] + p[0].append(p[3]) + else: + p[0] = [p[1]] + +#### A number. May be an integer or a float + +def p_number(p): + '''number : INTEGER + | FLOAT''' + p[0] = eval(p[1]) + +#### A signed number. + +def p_number_signed(p): + '''number : MINUS INTEGER + | MINUS FLOAT''' + p[0] = eval("-"+p[2]) + +#### List of targets for a print statement +#### Returns a list of tuples (label,expr) + +def p_plist(p): + '''plist : plist COMMA pitem + | pitem''' + if len(p) > 3: + p[0] = p[1] + p[0].append(p[3]) + else: + p[0] = [p[1]] + +def p_item_string(p): + '''pitem : STRING''' + p[0] = (p[1][1:-1],None) + +def p_item_string_expr(p): + '''pitem : STRING expr''' + p[0] = (p[1][1:-1],p[2]) + +def p_item_expr(p): + '''pitem : expr''' + p[0] = ("",p[1]) + +#### Empty + +def p_empty(p): + '''empty : ''' + +#### Catastrophic error handler +def p_error(p): + if not p: + print("SYNTAX ERROR AT EOF") + +bparser = yacc.yacc() + +def parse(data,debug=0): + bparser.error = 0 + p = bparser.parse(data,debug=debug) + if bparser.error: return None + return p + + + + + + + + + + + + + + diff --git a/simulators/gem5/ext/ply/example/BASIC/dim.bas b/simulators/gem5/ext/ply/example/BASIC/dim.bas new file mode 100644 index 00000000..87bd95b3 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/dim.bas @@ -0,0 +1,14 @@ +5 DIM A(50,15) +10 FOR I = 1 TO 50 +20 FOR J = 1 TO 15 +30 LET A(I,J) = I + J +35 REM PRINT I,J, A(I,J) +40 NEXT J +50 NEXT I +100 FOR I = 1 TO 50 +110 FOR J = 1 TO 15 +120 PRINT A(I,J), +130 NEXT J +140 PRINT +150 NEXT I +999 END diff --git a/simulators/gem5/ext/ply/example/BASIC/func.bas b/simulators/gem5/ext/ply/example/BASIC/func.bas new file mode 100644 index 00000000..447ee16a --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/func.bas @@ -0,0 +1,5 @@ +10 DEF FDX(X) = 2*X +20 FOR I = 0 TO 100 +30 PRINT FDX(I) +40 NEXT I +50 END diff --git a/simulators/gem5/ext/ply/example/BASIC/gcd.bas b/simulators/gem5/ext/ply/example/BASIC/gcd.bas new file mode 100644 index 00000000..d0b77460 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/gcd.bas @@ -0,0 +1,22 @@ +10 PRINT "A","B","C","GCD" +20 READ A,B,C +30 LET X = A +40 LET Y = B +50 GOSUB 200 +60 LET X = G +70 LET Y = C +80 GOSUB 200 +90 PRINT A, B, C, G +100 GOTO 20 +110 DATA 60, 90, 120 +120 DATA 38456, 64872, 98765 +130 DATA 32, 384, 72 +200 LET Q = INT(X/Y) +210 LET R = X - Q*Y +220 IF R = 0 THEN 300 +230 LET X = Y +240 LET Y = R +250 GOTO 200 +300 LET G = Y +310 RETURN +999 END diff --git a/simulators/gem5/ext/ply/example/BASIC/gosub.bas b/simulators/gem5/ext/ply/example/BASIC/gosub.bas new file mode 100644 index 00000000..99737b16 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/gosub.bas @@ -0,0 +1,13 @@ +100 LET X = 3 +110 GOSUB 400 +120 PRINT U, V, W +200 LET X = 5 +210 GOSUB 400 +220 LET Z = U + 2*V + 3*W +230 PRINT Z +240 GOTO 999 +400 LET U = X*X +410 LET V = X*X*X +420 LET W = X*X*X*X + X*X*X + X*X + X +430 RETURN +999 END diff --git a/simulators/gem5/ext/ply/example/BASIC/hello.bas b/simulators/gem5/ext/ply/example/BASIC/hello.bas new file mode 100644 index 00000000..cc6f0b0b --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/hello.bas @@ -0,0 +1,4 @@ +5 REM HELLO WORLD PROGAM +10 PRINT "HELLO WORLD" +99 END + diff --git a/simulators/gem5/ext/ply/example/BASIC/linear.bas b/simulators/gem5/ext/ply/example/BASIC/linear.bas new file mode 100644 index 00000000..56c08220 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/linear.bas @@ -0,0 +1,17 @@ +1 REM ::: SOLVE A SYSTEM OF LINEAR EQUATIONS +2 REM ::: A1*X1 + A2*X2 = B1 +3 REM ::: A3*X1 + A4*X2 = B2 +4 REM -------------------------------------- +10 READ A1, A2, A3, A4 +15 LET D = A1 * A4 - A3 * A2 +20 IF D = 0 THEN 65 +30 READ B1, B2 +37 LET X1 = (B1*A4 - B2*A2) / D +42 LET X2 = (A1*B2 - A3*B1) / D +55 PRINT X1, X2 +60 GOTO 30 +65 PRINT "NO UNIQUE SOLUTION" +70 DATA 1, 2, 4 +80 DATA 2, -7, 5 +85 DATA 1, 3, 4, -7 +90 END diff --git a/simulators/gem5/ext/ply/example/BASIC/maxsin.bas b/simulators/gem5/ext/ply/example/BASIC/maxsin.bas new file mode 100644 index 00000000..b9690153 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/maxsin.bas @@ -0,0 +1,12 @@ +5 PRINT "X VALUE", "SINE", "RESOLUTION" +10 READ D +20 LET M = -1 +30 FOR X = 0 TO 3 STEP D +40 IF SIN(X) <= M THEN 80 +50 LET X0 = X +60 LET M = SIN(X) +80 NEXT X +85 PRINT X0, M, D +90 GOTO 10 +100 DATA .1, .01, .001 +110 END diff --git a/simulators/gem5/ext/ply/example/BASIC/powers.bas b/simulators/gem5/ext/ply/example/BASIC/powers.bas new file mode 100644 index 00000000..a454dc3e --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/powers.bas @@ -0,0 +1,13 @@ +5 PRINT "THIS PROGRAM COMPUTES AND PRINTS THE NTH POWERS" +6 PRINT "OF THE NUMBERS LESS THAN OR EQUAL TO N FOR VARIOUS" +7 PRINT "N FROM 1 THROUGH 7" +8 PRINT +10 FOR N = 1 TO 7 +15 PRINT "N = "N +20 FOR I = 1 TO N +30 PRINT I^N, +40 NEXT I +50 PRINT +60 PRINT +70 NEXT N +80 END diff --git a/simulators/gem5/ext/ply/example/BASIC/rand.bas b/simulators/gem5/ext/ply/example/BASIC/rand.bas new file mode 100644 index 00000000..4ff7a146 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/rand.bas @@ -0,0 +1,4 @@ +10 FOR I = 1 TO 20 +20 PRINT INT(10*RND(0)) +30 NEXT I +40 END diff --git a/simulators/gem5/ext/ply/example/BASIC/sales.bas b/simulators/gem5/ext/ply/example/BASIC/sales.bas new file mode 100644 index 00000000..a39aefb7 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/sales.bas @@ -0,0 +1,20 @@ +10 FOR I = 1 TO 3 +20 READ P(I) +30 NEXT I +40 FOR I = 1 TO 3 +50 FOR J = 1 TO 5 +60 READ S(I,J) +70 NEXT J +80 NEXT I +90 FOR J = 1 TO 5 +100 LET S = 0 +110 FOR I = 1 TO 3 +120 LET S = S + P(I) * S(I,J) +130 NEXT I +140 PRINT "TOTAL SALES FOR SALESMAN"J, "$"S +150 NEXT J +200 DATA 1.25, 4.30, 2.50 +210 DATA 40, 20, 37, 29, 42 +220 DATA 10, 16, 3, 21, 8 +230 DATA 35, 47, 29, 16, 33 +300 END diff --git a/simulators/gem5/ext/ply/example/BASIC/sears.bas b/simulators/gem5/ext/ply/example/BASIC/sears.bas new file mode 100644 index 00000000..5ced3974 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/sears.bas @@ -0,0 +1,18 @@ +1 REM :: THIS PROGRAM COMPUTES HOW MANY TIMES YOU HAVE TO FOLD +2 REM :: A PIECE OF PAPER SO THAT IT IS TALLER THAN THE +3 REM :: SEARS TOWER. +4 REM :: S = HEIGHT OF TOWER (METERS) +5 REM :: T = THICKNESS OF PAPER (MILLIMETERS) +10 LET S = 442 +20 LET T = 0.1 +30 REM CONVERT T TO METERS +40 LET T = T * .001 +50 LET F = 1 +60 LET H = T +100 IF H > S THEN 200 +120 LET H = 2 * H +125 LET F = F + 1 +130 GOTO 100 +200 PRINT "NUMBER OF FOLDS ="F +220 PRINT "FINAL HEIGHT ="H +999 END diff --git a/simulators/gem5/ext/ply/example/BASIC/sqrt1.bas b/simulators/gem5/ext/ply/example/BASIC/sqrt1.bas new file mode 100644 index 00000000..6673a915 --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/sqrt1.bas @@ -0,0 +1,5 @@ +10 LET X = 0 +20 LET X = X + 1 +30 PRINT X, SQR(X) +40 IF X < 100 THEN 20 +50 END diff --git a/simulators/gem5/ext/ply/example/BASIC/sqrt2.bas b/simulators/gem5/ext/ply/example/BASIC/sqrt2.bas new file mode 100644 index 00000000..862d85ef --- /dev/null +++ b/simulators/gem5/ext/ply/example/BASIC/sqrt2.bas @@ -0,0 +1,4 @@ +10 FOR X = 1 TO 100 +20 PRINT X, SQR(X) +30 NEXT X +40 END diff --git a/simulators/gem5/ext/ply/example/GardenSnake/GardenSnake.py b/simulators/gem5/ext/ply/example/GardenSnake/GardenSnake.py new file mode 100644 index 00000000..2a7f45eb --- /dev/null +++ b/simulators/gem5/ext/ply/example/GardenSnake/GardenSnake.py @@ -0,0 +1,709 @@ +# GardenSnake - a parser generator demonstration program +# +# This implements a modified version of a subset of Python: +# - only 'def', 'return' and 'if' statements +# - 'if' only has 'then' clause (no elif nor else) +# - single-quoted strings only, content in raw format +# - numbers are decimal.Decimal instances (not integers or floats) +# - no print statment; use the built-in 'print' function +# - only < > == + - / * implemented (and unary + -) +# - assignment and tuple assignment work +# - no generators of any sort +# - no ... well, no quite a lot + +# Why? I'm thinking about a new indentation-based configuration +# language for a project and wanted to figure out how to do it. Once +# I got that working I needed a way to test it out. My original AST +# was dumb so I decided to target Python's AST and compile it into +# Python code. Plus, it's pretty cool that it only took a day or so +# from sitting down with Ply to having working code. + +# This uses David Beazley's Ply from http://www.dabeaz.com/ply/ + +# This work is hereby released into the Public Domain. To view a copy of +# the public domain dedication, visit +# http://creativecommons.org/licenses/publicdomain/ or send a letter to +# Creative Commons, 543 Howard Street, 5th Floor, San Francisco, +# California, 94105, USA. +# +# Portions of this work are derived from Python's Grammar definition +# and may be covered under the Python copyright and license +# +# Andrew Dalke / Dalke Scientific Software, LLC +# 30 August 2006 / Cape Town, South Africa + +# Changelog: +# 30 August - added link to CC license; removed the "swapcase" encoding + +# Modifications for inclusion in PLY distribution +import sys +sys.path.insert(0,"../..") +from ply import * + +##### Lexer ###### +#import lex +import decimal + +tokens = ( + 'DEF', + 'IF', + 'NAME', + 'NUMBER', # Python decimals + 'STRING', # single quoted strings only; syntax of raw strings + 'LPAR', + 'RPAR', + 'COLON', + 'EQ', + 'ASSIGN', + 'LT', + 'GT', + 'PLUS', + 'MINUS', + 'MULT', + 'DIV', + 'RETURN', + 'WS', + 'NEWLINE', + 'COMMA', + 'SEMICOLON', + 'INDENT', + 'DEDENT', + 'ENDMARKER', + ) + +#t_NUMBER = r'\d+' +# taken from decmial.py but without the leading sign +def t_NUMBER(t): + r"""(\d+(\.\d*)?|\.\d+)([eE][-+]? \d+)?""" + t.value = decimal.Decimal(t.value) + return t + +def t_STRING(t): + r"'([^\\']+|\\'|\\\\)*'" # I think this is right ... + t.value=t.value[1:-1].decode("string-escape") # .swapcase() # for fun + return t + +t_COLON = r':' +t_EQ = r'==' +t_ASSIGN = r'=' +t_LT = r'<' +t_GT = r'>' +t_PLUS = r'\+' +t_MINUS = r'-' +t_MULT = r'\*' +t_DIV = r'/' +t_COMMA = r',' +t_SEMICOLON = r';' + +# Ply nicely documented how to do this. + +RESERVED = { + "def": "DEF", + "if": "IF", + "return": "RETURN", + } + +def t_NAME(t): + r'[a-zA-Z_][a-zA-Z0-9_]*' + t.type = RESERVED.get(t.value, "NAME") + return t + +# Putting this before t_WS let it consume lines with only comments in +# them so the latter code never sees the WS part. Not consuming the +# newline. Needed for "if 1: #comment" +def t_comment(t): + r"[ ]*\043[^\n]*" # \043 is '#' + pass + + +# Whitespace +def t_WS(t): + r' [ ]+ ' + if t.lexer.at_line_start and t.lexer.paren_count == 0: + return t + +# Don't generate newline tokens when inside of parenthesis, eg +# a = (1, +# 2, 3) +def t_newline(t): + r'\n+' + t.lexer.lineno += len(t.value) + t.type = "NEWLINE" + if t.lexer.paren_count == 0: + return t + +def t_LPAR(t): + r'\(' + t.lexer.paren_count += 1 + return t + +def t_RPAR(t): + r'\)' + # check for underflow? should be the job of the parser + t.lexer.paren_count -= 1 + return t + + +def t_error(t): + raise SyntaxError("Unknown symbol %r" % (t.value[0],)) + print "Skipping", repr(t.value[0]) + t.lexer.skip(1) + +## I implemented INDENT / DEDENT generation as a post-processing filter + +# The original lex token stream contains WS and NEWLINE characters. +# WS will only occur before any other tokens on a line. + +# I have three filters. One tags tokens by adding two attributes. +# "must_indent" is True if the token must be indented from the +# previous code. The other is "at_line_start" which is True for WS +# and the first non-WS/non-NEWLINE on a line. It flags the check so +# see if the new line has changed indication level. + +# Python's syntax has three INDENT states +# 0) no colon hence no need to indent +# 1) "if 1: go()" - simple statements have a COLON but no need for an indent +# 2) "if 1:\n go()" - complex statements have a COLON NEWLINE and must indent +NO_INDENT = 0 +MAY_INDENT = 1 +MUST_INDENT = 2 + +# only care about whitespace at the start of a line +def track_tokens_filter(lexer, tokens): + lexer.at_line_start = at_line_start = True + indent = NO_INDENT + saw_colon = False + for token in tokens: + token.at_line_start = at_line_start + + if token.type == "COLON": + at_line_start = False + indent = MAY_INDENT + token.must_indent = False + + elif token.type == "NEWLINE": + at_line_start = True + if indent == MAY_INDENT: + indent = MUST_INDENT + token.must_indent = False + + elif token.type == "WS": + assert token.at_line_start == True + at_line_start = True + token.must_indent = False + + else: + # A real token; only indent after COLON NEWLINE + if indent == MUST_INDENT: + token.must_indent = True + else: + token.must_indent = False + at_line_start = False + indent = NO_INDENT + + yield token + lexer.at_line_start = at_line_start + +def _new_token(type, lineno): + tok = lex.LexToken() + tok.type = type + tok.value = None + tok.lineno = lineno + return tok + +# Synthesize a DEDENT tag +def DEDENT(lineno): + return _new_token("DEDENT", lineno) + +# Synthesize an INDENT tag +def INDENT(lineno): + return _new_token("INDENT", lineno) + + +# Track the indentation level and emit the right INDENT / DEDENT events. +def indentation_filter(tokens): + # A stack of indentation levels; will never pop item 0 + levels = [0] + token = None + depth = 0 + prev_was_ws = False + for token in tokens: +## if 1: +## print "Process", token, +## if token.at_line_start: +## print "at_line_start", +## if token.must_indent: +## print "must_indent", +## print + + # WS only occurs at the start of the line + # There may be WS followed by NEWLINE so + # only track the depth here. Don't indent/dedent + # until there's something real. + if token.type == "WS": + assert depth == 0 + depth = len(token.value) + prev_was_ws = True + # WS tokens are never passed to the parser + continue + + if token.type == "NEWLINE": + depth = 0 + if prev_was_ws or token.at_line_start: + # ignore blank lines + continue + # pass the other cases on through + yield token + continue + + # then it must be a real token (not WS, not NEWLINE) + # which can affect the indentation level + + prev_was_ws = False + if token.must_indent: + # The current depth must be larger than the previous level + if not (depth > levels[-1]): + raise IndentationError("expected an indented block") + + levels.append(depth) + yield INDENT(token.lineno) + + elif token.at_line_start: + # Must be on the same level or one of the previous levels + if depth == levels[-1]: + # At the same level + pass + elif depth > levels[-1]: + raise IndentationError("indentation increase but not in new block") + else: + # Back up; but only if it matches a previous level + try: + i = levels.index(depth) + except ValueError: + raise IndentationError("inconsistent indentation") + for _ in range(i+1, len(levels)): + yield DEDENT(token.lineno) + levels.pop() + + yield token + + ### Finished processing ### + + # Must dedent any remaining levels + if len(levels) > 1: + assert token is not None + for _ in range(1, len(levels)): + yield DEDENT(token.lineno) + + +# The top-level filter adds an ENDMARKER, if requested. +# Python's grammar uses it. +def filter(lexer, add_endmarker = True): + token = None + tokens = iter(lexer.token, None) + tokens = track_tokens_filter(lexer, tokens) + for token in indentation_filter(tokens): + yield token + + if add_endmarker: + lineno = 1 + if token is not None: + lineno = token.lineno + yield _new_token("ENDMARKER", lineno) + +# Combine Ply and my filters into a new lexer + +class IndentLexer(object): + def __init__(self, debug=0, optimize=0, lextab='lextab', reflags=0): + self.lexer = lex.lex(debug=debug, optimize=optimize, lextab=lextab, reflags=reflags) + self.token_stream = None + def input(self, s, add_endmarker=True): + self.lexer.paren_count = 0 + self.lexer.input(s) + self.token_stream = filter(self.lexer, add_endmarker) + def token(self): + try: + return self.token_stream.next() + except StopIteration: + return None + +########## Parser (tokens -> AST) ###### + +# also part of Ply +#import yacc + +# I use the Python AST +from compiler import ast + +# Helper function +def Assign(left, right): + names = [] + if isinstance(left, ast.Name): + # Single assignment on left + return ast.Assign([ast.AssName(left.name, 'OP_ASSIGN')], right) + elif isinstance(left, ast.Tuple): + # List of things - make sure they are Name nodes + names = [] + for child in left.getChildren(): + if not isinstance(child, ast.Name): + raise SyntaxError("that assignment not supported") + names.append(child.name) + ass_list = [ast.AssName(name, 'OP_ASSIGN') for name in names] + return ast.Assign([ast.AssTuple(ass_list)], right) + else: + raise SyntaxError("Can't do that yet") + + +# The grammar comments come from Python's Grammar/Grammar file + +## NB: compound_stmt in single_input is followed by extra NEWLINE! +# file_input: (NEWLINE | stmt)* ENDMARKER +def p_file_input_end(p): + """file_input_end : file_input ENDMARKER""" + p[0] = ast.Stmt(p[1]) +def p_file_input(p): + """file_input : file_input NEWLINE + | file_input stmt + | NEWLINE + | stmt""" + if isinstance(p[len(p)-1], basestring): + if len(p) == 3: + p[0] = p[1] + else: + p[0] = [] # p == 2 --> only a blank line + else: + if len(p) == 3: + p[0] = p[1] + p[2] + else: + p[0] = p[1] + + +# funcdef: [decorators] 'def' NAME parameters ':' suite +# ignoring decorators +def p_funcdef(p): + "funcdef : DEF NAME parameters COLON suite" + p[0] = ast.Function(None, p[2], tuple(p[3]), (), 0, None, p[5]) + +# parameters: '(' [varargslist] ')' +def p_parameters(p): + """parameters : LPAR RPAR + | LPAR varargslist RPAR""" + if len(p) == 3: + p[0] = [] + else: + p[0] = p[2] + + +# varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | +# highly simplified +def p_varargslist(p): + """varargslist : varargslist COMMA NAME + | NAME""" + if len(p) == 4: + p[0] = p[1] + p[3] + else: + p[0] = [p[1]] + +# stmt: simple_stmt | compound_stmt +def p_stmt_simple(p): + """stmt : simple_stmt""" + # simple_stmt is a list + p[0] = p[1] + +def p_stmt_compound(p): + """stmt : compound_stmt""" + p[0] = [p[1]] + +# simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE +def p_simple_stmt(p): + """simple_stmt : small_stmts NEWLINE + | small_stmts SEMICOLON NEWLINE""" + p[0] = p[1] + +def p_small_stmts(p): + """small_stmts : small_stmts SEMICOLON small_stmt + | small_stmt""" + if len(p) == 4: + p[0] = p[1] + [p[3]] + else: + p[0] = [p[1]] + +# small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | +# import_stmt | global_stmt | exec_stmt | assert_stmt +def p_small_stmt(p): + """small_stmt : flow_stmt + | expr_stmt""" + p[0] = p[1] + +# expr_stmt: testlist (augassign (yield_expr|testlist) | +# ('=' (yield_expr|testlist))*) +# augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | +# '<<=' | '>>=' | '**=' | '//=') +def p_expr_stmt(p): + """expr_stmt : testlist ASSIGN testlist + | testlist """ + if len(p) == 2: + # a list of expressions + p[0] = ast.Discard(p[1]) + else: + p[0] = Assign(p[1], p[3]) + +def p_flow_stmt(p): + "flow_stmt : return_stmt" + p[0] = p[1] + +# return_stmt: 'return' [testlist] +def p_return_stmt(p): + "return_stmt : RETURN testlist" + p[0] = ast.Return(p[2]) + + +def p_compound_stmt(p): + """compound_stmt : if_stmt + | funcdef""" + p[0] = p[1] + +def p_if_stmt(p): + 'if_stmt : IF test COLON suite' + p[0] = ast.If([(p[2], p[4])], None) + +def p_suite(p): + """suite : simple_stmt + | NEWLINE INDENT stmts DEDENT""" + if len(p) == 2: + p[0] = ast.Stmt(p[1]) + else: + p[0] = ast.Stmt(p[3]) + + +def p_stmts(p): + """stmts : stmts stmt + | stmt""" + if len(p) == 3: + p[0] = p[1] + p[2] + else: + p[0] = p[1] + +## No using Python's approach because Ply supports precedence + +# comparison: expr (comp_op expr)* +# arith_expr: term (('+'|'-') term)* +# term: factor (('*'|'/'|'%'|'//') factor)* +# factor: ('+'|'-'|'~') factor | power +# comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' + +def make_lt_compare((left, right)): + return ast.Compare(left, [('<', right),]) +def make_gt_compare((left, right)): + return ast.Compare(left, [('>', right),]) +def make_eq_compare((left, right)): + return ast.Compare(left, [('==', right),]) + + +binary_ops = { + "+": ast.Add, + "-": ast.Sub, + "*": ast.Mul, + "/": ast.Div, + "<": make_lt_compare, + ">": make_gt_compare, + "==": make_eq_compare, +} +unary_ops = { + "+": ast.UnaryAdd, + "-": ast.UnarySub, + } +precedence = ( + ("left", "EQ", "GT", "LT"), + ("left", "PLUS", "MINUS"), + ("left", "MULT", "DIV"), + ) + +def p_comparison(p): + """comparison : comparison PLUS comparison + | comparison MINUS comparison + | comparison MULT comparison + | comparison DIV comparison + | comparison LT comparison + | comparison EQ comparison + | comparison GT comparison + | PLUS comparison + | MINUS comparison + | power""" + if len(p) == 4: + p[0] = binary_ops[p[2]]((p[1], p[3])) + elif len(p) == 3: + p[0] = unary_ops[p[1]](p[2]) + else: + p[0] = p[1] + +# power: atom trailer* ['**' factor] +# trailers enables function calls. I only allow one level of calls +# so this is 'trailer' +def p_power(p): + """power : atom + | atom trailer""" + if len(p) == 2: + p[0] = p[1] + else: + if p[2][0] == "CALL": + p[0] = ast.CallFunc(p[1], p[2][1], None, None) + else: + raise AssertionError("not implemented") + +def p_atom_name(p): + """atom : NAME""" + p[0] = ast.Name(p[1]) + +def p_atom_number(p): + """atom : NUMBER + | STRING""" + p[0] = ast.Const(p[1]) + +def p_atom_tuple(p): + """atom : LPAR testlist RPAR""" + p[0] = p[2] + +# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +def p_trailer(p): + "trailer : LPAR arglist RPAR" + p[0] = ("CALL", p[2]) + +# testlist: test (',' test)* [','] +# Contains shift/reduce error +def p_testlist(p): + """testlist : testlist_multi COMMA + | testlist_multi """ + if len(p) == 2: + p[0] = p[1] + else: + # May need to promote singleton to tuple + if isinstance(p[1], list): + p[0] = p[1] + else: + p[0] = [p[1]] + # Convert into a tuple? + if isinstance(p[0], list): + p[0] = ast.Tuple(p[0]) + +def p_testlist_multi(p): + """testlist_multi : testlist_multi COMMA test + | test""" + if len(p) == 2: + # singleton + p[0] = p[1] + else: + if isinstance(p[1], list): + p[0] = p[1] + [p[3]] + else: + # singleton -> tuple + p[0] = [p[1], p[3]] + + +# test: or_test ['if' or_test 'else' test] | lambdef +# as I don't support 'and', 'or', and 'not' this works down to 'comparison' +def p_test(p): + "test : comparison" + p[0] = p[1] + + + +# arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +# XXX INCOMPLETE: this doesn't allow the trailing comma +def p_arglist(p): + """arglist : arglist COMMA argument + | argument""" + if len(p) == 4: + p[0] = p[1] + [p[3]] + else: + p[0] = [p[1]] + +# argument: test [gen_for] | test '=' test # Really [keyword '='] test +def p_argument(p): + "argument : test" + p[0] = p[1] + +def p_error(p): + #print "Error!", repr(p) + raise SyntaxError(p) + + +class GardenSnakeParser(object): + def __init__(self, lexer = None): + if lexer is None: + lexer = IndentLexer() + self.lexer = lexer + self.parser = yacc.yacc(start="file_input_end") + + def parse(self, code): + self.lexer.input(code) + result = self.parser.parse(lexer = self.lexer) + return ast.Module(None, result) + + +###### Code generation ###### + +from compiler import misc, syntax, pycodegen + +class GardenSnakeCompiler(object): + def __init__(self): + self.parser = GardenSnakeParser() + def compile(self, code, filename=""): + tree = self.parser.parse(code) + #print tree + misc.set_filename(filename, tree) + syntax.check(tree) + gen = pycodegen.ModuleCodeGenerator(tree) + code = gen.getCode() + return code + +####### Test code ####### + +compile = GardenSnakeCompiler().compile + +code = r""" + +print('LET\'S TRY THIS \\OUT') + +#Comment here +def x(a): + print('called with',a) + if a == 1: + return 2 + if a*2 > 10: return 999 / 4 + # Another comment here + + return a+2*3 + +ints = (1, 2, + 3, 4, +5) +print('mutiline-expression', ints) + +t = 4+1/3*2+6*(9-5+1) +print('predence test; should be 34+2/3:', t, t==(34+2/3)) + +print('numbers', 1,2,3,4,5) +if 1: + 8 + a=9 + print(x(a)) + +print(x(1)) +print(x(2)) +print(x(8),'3') +print('this is decimal', 1/5) +print('BIG DECIMAL', 1.234567891234567e12345) + +""" + +# Set up the GardenSnake run-time environment +def print_(*args): + print "-->", " ".join(map(str,args)) + +globals()["print"] = print_ + +compiled_code = compile(code) + +exec compiled_code in globals() +print "Done" diff --git a/simulators/gem5/ext/ply/example/GardenSnake/README b/simulators/gem5/ext/ply/example/GardenSnake/README new file mode 100644 index 00000000..4d8be2db --- /dev/null +++ b/simulators/gem5/ext/ply/example/GardenSnake/README @@ -0,0 +1,5 @@ +This example is Andrew Dalke's GardenSnake language. It shows how to process an +indentation-like language like Python. Further details can be found here: + +http://dalkescientific.com/writings/diary/archive/2006/08/30/gardensnake_language.html + diff --git a/simulators/gem5/ext/ply/example/README b/simulators/gem5/ext/ply/example/README new file mode 100644 index 00000000..63519b55 --- /dev/null +++ b/simulators/gem5/ext/ply/example/README @@ -0,0 +1,10 @@ +Simple examples: + calc - Simple calculator + classcalc - Simple calculate defined as a class + +Complex examples + ansic - ANSI C grammar from K&R + BASIC - A small BASIC interpreter + GardenSnake - A simple python-like language + yply - Converts Unix yacc files to PLY programs. + diff --git a/simulators/gem5/ext/ply/example/ansic/README b/simulators/gem5/ext/ply/example/ansic/README new file mode 100644 index 00000000..e049d3b4 --- /dev/null +++ b/simulators/gem5/ext/ply/example/ansic/README @@ -0,0 +1,2 @@ +This example is incomplete. Was going to specify an ANSI C parser. +This is part of it. diff --git a/simulators/gem5/ext/ply/example/ansic/clex.py b/simulators/gem5/ext/ply/example/ansic/clex.py new file mode 100644 index 00000000..37fdd8e6 --- /dev/null +++ b/simulators/gem5/ext/ply/example/ansic/clex.py @@ -0,0 +1,164 @@ +# ---------------------------------------------------------------------- +# clex.py +# +# A lexer for ANSI C. +# ---------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +import ply.lex as lex + +# Reserved words +reserved = ( + 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', 'CONTINUE', 'DEFAULT', 'DO', 'DOUBLE', + 'ELSE', 'ENUM', 'EXTERN', 'FLOAT', 'FOR', 'GOTO', 'IF', 'INT', 'LONG', 'REGISTER', + 'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT', 'SWITCH', 'TYPEDEF', + 'UNION', 'UNSIGNED', 'VOID', 'VOLATILE', 'WHILE', + ) + +tokens = reserved + ( + # Literals (identifier, integer constant, float constant, string constant, char const) + 'ID', 'TYPEID', 'ICONST', 'FCONST', 'SCONST', 'CCONST', + + # Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=) + 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', + 'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT', + 'LOR', 'LAND', 'LNOT', + 'LT', 'LE', 'GT', 'GE', 'EQ', 'NE', + + # Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=) + 'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL', + 'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL', + + # Increment/decrement (++,--) + 'PLUSPLUS', 'MINUSMINUS', + + # Structure dereference (->) + 'ARROW', + + # Conditional operator (?) + 'CONDOP', + + # Delimeters ( ) [ ] { } , . ; : + 'LPAREN', 'RPAREN', + 'LBRACKET', 'RBRACKET', + 'LBRACE', 'RBRACE', + 'COMMA', 'PERIOD', 'SEMI', 'COLON', + + # Ellipsis (...) + 'ELLIPSIS', + ) + +# Completely ignored characters +t_ignore = ' \t\x0c' + +# Newlines +def t_NEWLINE(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +# Operators +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_MOD = r'%' +t_OR = r'\|' +t_AND = r'&' +t_NOT = r'~' +t_XOR = r'\^' +t_LSHIFT = r'<<' +t_RSHIFT = r'>>' +t_LOR = r'\|\|' +t_LAND = r'&&' +t_LNOT = r'!' +t_LT = r'<' +t_GT = r'>' +t_LE = r'<=' +t_GE = r'>=' +t_EQ = r'==' +t_NE = r'!=' + +# Assignment operators + +t_EQUALS = r'=' +t_TIMESEQUAL = r'\*=' +t_DIVEQUAL = r'/=' +t_MODEQUAL = r'%=' +t_PLUSEQUAL = r'\+=' +t_MINUSEQUAL = r'-=' +t_LSHIFTEQUAL = r'<<=' +t_RSHIFTEQUAL = r'>>=' +t_ANDEQUAL = r'&=' +t_OREQUAL = r'\|=' +t_XOREQUAL = r'^=' + +# Increment/decrement +t_PLUSPLUS = r'\+\+' +t_MINUSMINUS = r'--' + +# -> +t_ARROW = r'->' + +# ? +t_CONDOP = r'\?' + +# Delimeters +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_LBRACKET = r'\[' +t_RBRACKET = r'\]' +t_LBRACE = r'\{' +t_RBRACE = r'\}' +t_COMMA = r',' +t_PERIOD = r'\.' +t_SEMI = r';' +t_COLON = r':' +t_ELLIPSIS = r'\.\.\.' + +# Identifiers and reserved words + +reserved_map = { } +for r in reserved: + reserved_map[r.lower()] = r + +def t_ID(t): + r'[A-Za-z_][\w_]*' + t.type = reserved_map.get(t.value,"ID") + return t + +# Integer literal +t_ICONST = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?' + +# Floating literal +t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' + +# String literal +t_SCONST = r'\"([^\\\n]|(\\.))*?\"' + +# Character constant 'c' or L'c' +t_CCONST = r'(L)?\'([^\\\n]|(\\.))*?\'' + +# Comments +def t_comment(t): + r'/\*(.|\n)*?\*/' + t.lexer.lineno += t.value.count('\n') + +# Preprocessor directive (ignored) +def t_preprocessor(t): + r'\#(.)*?\n' + t.lexer.lineno += 1 + +def t_error(t): + print("Illegal character %s" % repr(t.value[0])) + t.lexer.skip(1) + +lexer = lex.lex(optimize=1) +if __name__ == "__main__": + lex.runmain(lexer) + + + + + diff --git a/simulators/gem5/ext/ply/example/ansic/cparse.py b/simulators/gem5/ext/ply/example/ansic/cparse.py new file mode 100644 index 00000000..c9b91645 --- /dev/null +++ b/simulators/gem5/ext/ply/example/ansic/cparse.py @@ -0,0 +1,863 @@ +# ----------------------------------------------------------------------------- +# cparse.py +# +# Simple parser for ANSI C. Based on the grammar in K&R, 2nd Ed. +# ----------------------------------------------------------------------------- + +import sys +import clex +import ply.yacc as yacc + +# Get the token map +tokens = clex.tokens + +# translation-unit: + +def p_translation_unit_1(t): + 'translation_unit : external_declaration' + pass + +def p_translation_unit_2(t): + 'translation_unit : translation_unit external_declaration' + pass + +# external-declaration: + +def p_external_declaration_1(t): + 'external_declaration : function_definition' + pass + +def p_external_declaration_2(t): + 'external_declaration : declaration' + pass + +# function-definition: + +def p_function_definition_1(t): + 'function_definition : declaration_specifiers declarator declaration_list compound_statement' + pass + +def p_function_definition_2(t): + 'function_definition : declarator declaration_list compound_statement' + pass + +def p_function_definition_3(t): + 'function_definition : declarator compound_statement' + pass + +def p_function_definition_4(t): + 'function_definition : declaration_specifiers declarator compound_statement' + pass + +# declaration: + +def p_declaration_1(t): + 'declaration : declaration_specifiers init_declarator_list SEMI' + pass + +def p_declaration_2(t): + 'declaration : declaration_specifiers SEMI' + pass + +# declaration-list: + +def p_declaration_list_1(t): + 'declaration_list : declaration' + pass + +def p_declaration_list_2(t): + 'declaration_list : declaration_list declaration ' + pass + +# declaration-specifiers +def p_declaration_specifiers_1(t): + 'declaration_specifiers : storage_class_specifier declaration_specifiers' + pass + +def p_declaration_specifiers_2(t): + 'declaration_specifiers : type_specifier declaration_specifiers' + pass + +def p_declaration_specifiers_3(t): + 'declaration_specifiers : type_qualifier declaration_specifiers' + pass + +def p_declaration_specifiers_4(t): + 'declaration_specifiers : storage_class_specifier' + pass + +def p_declaration_specifiers_5(t): + 'declaration_specifiers : type_specifier' + pass + +def p_declaration_specifiers_6(t): + 'declaration_specifiers : type_qualifier' + pass + +# storage-class-specifier +def p_storage_class_specifier(t): + '''storage_class_specifier : AUTO + | REGISTER + | STATIC + | EXTERN + | TYPEDEF + ''' + pass + +# type-specifier: +def p_type_specifier(t): + '''type_specifier : VOID + | CHAR + | SHORT + | INT + | LONG + | FLOAT + | DOUBLE + | SIGNED + | UNSIGNED + | struct_or_union_specifier + | enum_specifier + | TYPEID + ''' + pass + +# type-qualifier: +def p_type_qualifier(t): + '''type_qualifier : CONST + | VOLATILE''' + pass + +# struct-or-union-specifier + +def p_struct_or_union_specifier_1(t): + 'struct_or_union_specifier : struct_or_union ID LBRACE struct_declaration_list RBRACE' + pass + +def p_struct_or_union_specifier_2(t): + 'struct_or_union_specifier : struct_or_union LBRACE struct_declaration_list RBRACE' + pass + +def p_struct_or_union_specifier_3(t): + 'struct_or_union_specifier : struct_or_union ID' + pass + +# struct-or-union: +def p_struct_or_union(t): + '''struct_or_union : STRUCT + | UNION + ''' + pass + +# struct-declaration-list: + +def p_struct_declaration_list_1(t): + 'struct_declaration_list : struct_declaration' + pass + +def p_struct_declaration_list_2(t): + 'struct_declaration_list : struct_declaration_list struct_declaration' + pass + +# init-declarator-list: + +def p_init_declarator_list_1(t): + 'init_declarator_list : init_declarator' + pass + +def p_init_declarator_list_2(t): + 'init_declarator_list : init_declarator_list COMMA init_declarator' + pass + +# init-declarator + +def p_init_declarator_1(t): + 'init_declarator : declarator' + pass + +def p_init_declarator_2(t): + 'init_declarator : declarator EQUALS initializer' + pass + +# struct-declaration: + +def p_struct_declaration(t): + 'struct_declaration : specifier_qualifier_list struct_declarator_list SEMI' + pass + +# specifier-qualifier-list: + +def p_specifier_qualifier_list_1(t): + 'specifier_qualifier_list : type_specifier specifier_qualifier_list' + pass + +def p_specifier_qualifier_list_2(t): + 'specifier_qualifier_list : type_specifier' + pass + +def p_specifier_qualifier_list_3(t): + 'specifier_qualifier_list : type_qualifier specifier_qualifier_list' + pass + +def p_specifier_qualifier_list_4(t): + 'specifier_qualifier_list : type_qualifier' + pass + +# struct-declarator-list: + +def p_struct_declarator_list_1(t): + 'struct_declarator_list : struct_declarator' + pass + +def p_struct_declarator_list_2(t): + 'struct_declarator_list : struct_declarator_list COMMA struct_declarator' + pass + +# struct-declarator: + +def p_struct_declarator_1(t): + 'struct_declarator : declarator' + pass + +def p_struct_declarator_2(t): + 'struct_declarator : declarator COLON constant_expression' + pass + +def p_struct_declarator_3(t): + 'struct_declarator : COLON constant_expression' + pass + +# enum-specifier: + +def p_enum_specifier_1(t): + 'enum_specifier : ENUM ID LBRACE enumerator_list RBRACE' + pass + +def p_enum_specifier_2(t): + 'enum_specifier : ENUM LBRACE enumerator_list RBRACE' + pass + +def p_enum_specifier_3(t): + 'enum_specifier : ENUM ID' + pass + +# enumerator_list: +def p_enumerator_list_1(t): + 'enumerator_list : enumerator' + pass + +def p_enumerator_list_2(t): + 'enumerator_list : enumerator_list COMMA enumerator' + pass + +# enumerator: +def p_enumerator_1(t): + 'enumerator : ID' + pass + +def p_enumerator_2(t): + 'enumerator : ID EQUALS constant_expression' + pass + +# declarator: + +def p_declarator_1(t): + 'declarator : pointer direct_declarator' + pass + +def p_declarator_2(t): + 'declarator : direct_declarator' + pass + +# direct-declarator: + +def p_direct_declarator_1(t): + 'direct_declarator : ID' + pass + +def p_direct_declarator_2(t): + 'direct_declarator : LPAREN declarator RPAREN' + pass + +def p_direct_declarator_3(t): + 'direct_declarator : direct_declarator LBRACKET constant_expression_opt RBRACKET' + pass + +def p_direct_declarator_4(t): + 'direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN ' + pass + +def p_direct_declarator_5(t): + 'direct_declarator : direct_declarator LPAREN identifier_list RPAREN ' + pass + +def p_direct_declarator_6(t): + 'direct_declarator : direct_declarator LPAREN RPAREN ' + pass + +# pointer: +def p_pointer_1(t): + 'pointer : TIMES type_qualifier_list' + pass + +def p_pointer_2(t): + 'pointer : TIMES' + pass + +def p_pointer_3(t): + 'pointer : TIMES type_qualifier_list pointer' + pass + +def p_pointer_4(t): + 'pointer : TIMES pointer' + pass + +# type-qualifier-list: + +def p_type_qualifier_list_1(t): + 'type_qualifier_list : type_qualifier' + pass + +def p_type_qualifier_list_2(t): + 'type_qualifier_list : type_qualifier_list type_qualifier' + pass + +# parameter-type-list: + +def p_parameter_type_list_1(t): + 'parameter_type_list : parameter_list' + pass + +def p_parameter_type_list_2(t): + 'parameter_type_list : parameter_list COMMA ELLIPSIS' + pass + +# parameter-list: + +def p_parameter_list_1(t): + 'parameter_list : parameter_declaration' + pass + +def p_parameter_list_2(t): + 'parameter_list : parameter_list COMMA parameter_declaration' + pass + +# parameter-declaration: +def p_parameter_declaration_1(t): + 'parameter_declaration : declaration_specifiers declarator' + pass + +def p_parameter_declaration_2(t): + 'parameter_declaration : declaration_specifiers abstract_declarator_opt' + pass + +# identifier-list: +def p_identifier_list_1(t): + 'identifier_list : ID' + pass + +def p_identifier_list_2(t): + 'identifier_list : identifier_list COMMA ID' + pass + +# initializer: + +def p_initializer_1(t): + 'initializer : assignment_expression' + pass + +def p_initializer_2(t): + '''initializer : LBRACE initializer_list RBRACE + | LBRACE initializer_list COMMA RBRACE''' + pass + +# initializer-list: + +def p_initializer_list_1(t): + 'initializer_list : initializer' + pass + +def p_initializer_list_2(t): + 'initializer_list : initializer_list COMMA initializer' + pass + +# type-name: + +def p_type_name(t): + 'type_name : specifier_qualifier_list abstract_declarator_opt' + pass + +def p_abstract_declarator_opt_1(t): + 'abstract_declarator_opt : empty' + pass + +def p_abstract_declarator_opt_2(t): + 'abstract_declarator_opt : abstract_declarator' + pass + +# abstract-declarator: + +def p_abstract_declarator_1(t): + 'abstract_declarator : pointer ' + pass + +def p_abstract_declarator_2(t): + 'abstract_declarator : pointer direct_abstract_declarator' + pass + +def p_abstract_declarator_3(t): + 'abstract_declarator : direct_abstract_declarator' + pass + +# direct-abstract-declarator: + +def p_direct_abstract_declarator_1(t): + 'direct_abstract_declarator : LPAREN abstract_declarator RPAREN' + pass + +def p_direct_abstract_declarator_2(t): + 'direct_abstract_declarator : direct_abstract_declarator LBRACKET constant_expression_opt RBRACKET' + pass + +def p_direct_abstract_declarator_3(t): + 'direct_abstract_declarator : LBRACKET constant_expression_opt RBRACKET' + pass + +def p_direct_abstract_declarator_4(t): + 'direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN' + pass + +def p_direct_abstract_declarator_5(t): + 'direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN' + pass + +# Optional fields in abstract declarators + +def p_constant_expression_opt_1(t): + 'constant_expression_opt : empty' + pass + +def p_constant_expression_opt_2(t): + 'constant_expression_opt : constant_expression' + pass + +def p_parameter_type_list_opt_1(t): + 'parameter_type_list_opt : empty' + pass + +def p_parameter_type_list_opt_2(t): + 'parameter_type_list_opt : parameter_type_list' + pass + +# statement: + +def p_statement(t): + ''' + statement : labeled_statement + | expression_statement + | compound_statement + | selection_statement + | iteration_statement + | jump_statement + ''' + pass + +# labeled-statement: + +def p_labeled_statement_1(t): + 'labeled_statement : ID COLON statement' + pass + +def p_labeled_statement_2(t): + 'labeled_statement : CASE constant_expression COLON statement' + pass + +def p_labeled_statement_3(t): + 'labeled_statement : DEFAULT COLON statement' + pass + +# expression-statement: +def p_expression_statement(t): + 'expression_statement : expression_opt SEMI' + pass + +# compound-statement: + +def p_compound_statement_1(t): + 'compound_statement : LBRACE declaration_list statement_list RBRACE' + pass + +def p_compound_statement_2(t): + 'compound_statement : LBRACE statement_list RBRACE' + pass + +def p_compound_statement_3(t): + 'compound_statement : LBRACE declaration_list RBRACE' + pass + +def p_compound_statement_4(t): + 'compound_statement : LBRACE RBRACE' + pass + +# statement-list: + +def p_statement_list_1(t): + 'statement_list : statement' + pass + +def p_statement_list_2(t): + 'statement_list : statement_list statement' + pass + +# selection-statement + +def p_selection_statement_1(t): + 'selection_statement : IF LPAREN expression RPAREN statement' + pass + +def p_selection_statement_2(t): + 'selection_statement : IF LPAREN expression RPAREN statement ELSE statement ' + pass + +def p_selection_statement_3(t): + 'selection_statement : SWITCH LPAREN expression RPAREN statement ' + pass + +# iteration_statement: + +def p_iteration_statement_1(t): + 'iteration_statement : WHILE LPAREN expression RPAREN statement' + pass + +def p_iteration_statement_2(t): + 'iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement ' + pass + +def p_iteration_statement_3(t): + 'iteration_statement : DO statement WHILE LPAREN expression RPAREN SEMI' + pass + +# jump_statement: + +def p_jump_statement_1(t): + 'jump_statement : GOTO ID SEMI' + pass + +def p_jump_statement_2(t): + 'jump_statement : CONTINUE SEMI' + pass + +def p_jump_statement_3(t): + 'jump_statement : BREAK SEMI' + pass + +def p_jump_statement_4(t): + 'jump_statement : RETURN expression_opt SEMI' + pass + +def p_expression_opt_1(t): + 'expression_opt : empty' + pass + +def p_expression_opt_2(t): + 'expression_opt : expression' + pass + +# expression: +def p_expression_1(t): + 'expression : assignment_expression' + pass + +def p_expression_2(t): + 'expression : expression COMMA assignment_expression' + pass + +# assigment_expression: +def p_assignment_expression_1(t): + 'assignment_expression : conditional_expression' + pass + +def p_assignment_expression_2(t): + 'assignment_expression : unary_expression assignment_operator assignment_expression' + pass + +# assignment_operator: +def p_assignment_operator(t): + ''' + assignment_operator : EQUALS + | TIMESEQUAL + | DIVEQUAL + | MODEQUAL + | PLUSEQUAL + | MINUSEQUAL + | LSHIFTEQUAL + | RSHIFTEQUAL + | ANDEQUAL + | OREQUAL + | XOREQUAL + ''' + pass + +# conditional-expression +def p_conditional_expression_1(t): + 'conditional_expression : logical_or_expression' + pass + +def p_conditional_expression_2(t): + 'conditional_expression : logical_or_expression CONDOP expression COLON conditional_expression ' + pass + +# constant-expression + +def p_constant_expression(t): + 'constant_expression : conditional_expression' + pass + +# logical-or-expression + +def p_logical_or_expression_1(t): + 'logical_or_expression : logical_and_expression' + pass + +def p_logical_or_expression_2(t): + 'logical_or_expression : logical_or_expression LOR logical_and_expression' + pass + +# logical-and-expression + +def p_logical_and_expression_1(t): + 'logical_and_expression : inclusive_or_expression' + pass + +def p_logical_and_expression_2(t): + 'logical_and_expression : logical_and_expression LAND inclusive_or_expression' + pass + +# inclusive-or-expression: + +def p_inclusive_or_expression_1(t): + 'inclusive_or_expression : exclusive_or_expression' + pass + +def p_inclusive_or_expression_2(t): + 'inclusive_or_expression : inclusive_or_expression OR exclusive_or_expression' + pass + +# exclusive-or-expression: + +def p_exclusive_or_expression_1(t): + 'exclusive_or_expression : and_expression' + pass + +def p_exclusive_or_expression_2(t): + 'exclusive_or_expression : exclusive_or_expression XOR and_expression' + pass + +# AND-expression + +def p_and_expression_1(t): + 'and_expression : equality_expression' + pass + +def p_and_expression_2(t): + 'and_expression : and_expression AND equality_expression' + pass + + +# equality-expression: +def p_equality_expression_1(t): + 'equality_expression : relational_expression' + pass + +def p_equality_expression_2(t): + 'equality_expression : equality_expression EQ relational_expression' + pass + +def p_equality_expression_3(t): + 'equality_expression : equality_expression NE relational_expression' + pass + + +# relational-expression: +def p_relational_expression_1(t): + 'relational_expression : shift_expression' + pass + +def p_relational_expression_2(t): + 'relational_expression : relational_expression LT shift_expression' + pass + +def p_relational_expression_3(t): + 'relational_expression : relational_expression GT shift_expression' + pass + +def p_relational_expression_4(t): + 'relational_expression : relational_expression LE shift_expression' + pass + +def p_relational_expression_5(t): + 'relational_expression : relational_expression GE shift_expression' + pass + +# shift-expression + +def p_shift_expression_1(t): + 'shift_expression : additive_expression' + pass + +def p_shift_expression_2(t): + 'shift_expression : shift_expression LSHIFT additive_expression' + pass + +def p_shift_expression_3(t): + 'shift_expression : shift_expression RSHIFT additive_expression' + pass + +# additive-expression + +def p_additive_expression_1(t): + 'additive_expression : multiplicative_expression' + pass + +def p_additive_expression_2(t): + 'additive_expression : additive_expression PLUS multiplicative_expression' + pass + +def p_additive_expression_3(t): + 'additive_expression : additive_expression MINUS multiplicative_expression' + pass + +# multiplicative-expression + +def p_multiplicative_expression_1(t): + 'multiplicative_expression : cast_expression' + pass + +def p_multiplicative_expression_2(t): + 'multiplicative_expression : multiplicative_expression TIMES cast_expression' + pass + +def p_multiplicative_expression_3(t): + 'multiplicative_expression : multiplicative_expression DIVIDE cast_expression' + pass + +def p_multiplicative_expression_4(t): + 'multiplicative_expression : multiplicative_expression MOD cast_expression' + pass + +# cast-expression: + +def p_cast_expression_1(t): + 'cast_expression : unary_expression' + pass + +def p_cast_expression_2(t): + 'cast_expression : LPAREN type_name RPAREN cast_expression' + pass + +# unary-expression: +def p_unary_expression_1(t): + 'unary_expression : postfix_expression' + pass + +def p_unary_expression_2(t): + 'unary_expression : PLUSPLUS unary_expression' + pass + +def p_unary_expression_3(t): + 'unary_expression : MINUSMINUS unary_expression' + pass + +def p_unary_expression_4(t): + 'unary_expression : unary_operator cast_expression' + pass + +def p_unary_expression_5(t): + 'unary_expression : SIZEOF unary_expression' + pass + +def p_unary_expression_6(t): + 'unary_expression : SIZEOF LPAREN type_name RPAREN' + pass + +#unary-operator +def p_unary_operator(t): + '''unary_operator : AND + | TIMES + | PLUS + | MINUS + | NOT + | LNOT ''' + pass + +# postfix-expression: +def p_postfix_expression_1(t): + 'postfix_expression : primary_expression' + pass + +def p_postfix_expression_2(t): + 'postfix_expression : postfix_expression LBRACKET expression RBRACKET' + pass + +def p_postfix_expression_3(t): + 'postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN' + pass + +def p_postfix_expression_4(t): + 'postfix_expression : postfix_expression LPAREN RPAREN' + pass + +def p_postfix_expression_5(t): + 'postfix_expression : postfix_expression PERIOD ID' + pass + +def p_postfix_expression_6(t): + 'postfix_expression : postfix_expression ARROW ID' + pass + +def p_postfix_expression_7(t): + 'postfix_expression : postfix_expression PLUSPLUS' + pass + +def p_postfix_expression_8(t): + 'postfix_expression : postfix_expression MINUSMINUS' + pass + +# primary-expression: +def p_primary_expression(t): + '''primary_expression : ID + | constant + | SCONST + | LPAREN expression RPAREN''' + pass + +# argument-expression-list: +def p_argument_expression_list(t): + '''argument_expression_list : assignment_expression + | argument_expression_list COMMA assignment_expression''' + pass + +# constant: +def p_constant(t): + '''constant : ICONST + | FCONST + | CCONST''' + pass + + +def p_empty(t): + 'empty : ' + pass + +def p_error(t): + print("Whoa. We're hosed") + +import profile +# Build the grammar + +yacc.yacc(method='LALR') + +#profile.run("yacc.yacc(method='LALR')") + + + + diff --git a/simulators/gem5/ext/ply/example/calc/calc.py b/simulators/gem5/ext/ply/example/calc/calc.py new file mode 100644 index 00000000..b9237804 --- /dev/null +++ b/simulators/gem5/ext/ply/example/calc/calc.py @@ -0,0 +1,107 @@ +# ----------------------------------------------------------------------------- +# calc.py +# +# A simple calculator with variables. This is from O'Reilly's +# "Lex and Yacc", p. 63. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +tokens = ( + 'NAME','NUMBER', + ) + +literals = ['=','+','-','*','/', '(',')'] + +# Tokens + +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + t.value = int(t.value) + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex() + +# Parsing rules + +precedence = ( + ('left','+','-'), + ('left','*','/'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(p): + 'statement : NAME "=" expression' + names[p[1]] = p[3] + +def p_statement_expr(p): + 'statement : expression' + print(p[1]) + +def p_expression_binop(p): + '''expression : expression '+' expression + | expression '-' expression + | expression '*' expression + | expression '/' expression''' + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + +def p_expression_uminus(p): + "expression : '-' expression %prec UMINUS" + p[0] = -p[2] + +def p_expression_group(p): + "expression : '(' expression ')'" + p[0] = p[2] + +def p_expression_number(p): + "expression : NUMBER" + p[0] = p[1] + +def p_expression_name(p): + "expression : NAME" + try: + p[0] = names[p[1]] + except LookupError: + print("Undefined name '%s'" % p[1]) + p[0] = 0 + +def p_error(p): + if p: + print("Syntax error at '%s'" % p.value) + else: + print("Syntax error at EOF") + +import ply.yacc as yacc +yacc.yacc() + +while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + if not s: continue + yacc.parse(s) diff --git a/simulators/gem5/ext/ply/example/calcdebug/calc.py b/simulators/gem5/ext/ply/example/calcdebug/calc.py new file mode 100644 index 00000000..6732f9f3 --- /dev/null +++ b/simulators/gem5/ext/ply/example/calcdebug/calc.py @@ -0,0 +1,113 @@ +# ----------------------------------------------------------------------------- +# calc.py +# +# This example shows how to run the parser in a debugging mode +# with output routed to a logging object. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +tokens = ( + 'NAME','NUMBER', + ) + +literals = ['=','+','-','*','/', '(',')'] + +# Tokens + +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + t.value = int(t.value) + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex() + +# Parsing rules + +precedence = ( + ('left','+','-'), + ('left','*','/'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(p): + 'statement : NAME "=" expression' + names[p[1]] = p[3] + +def p_statement_expr(p): + 'statement : expression' + print(p[1]) + +def p_expression_binop(p): + '''expression : expression '+' expression + | expression '-' expression + | expression '*' expression + | expression '/' expression''' + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + +def p_expression_uminus(p): + "expression : '-' expression %prec UMINUS" + p[0] = -p[2] + +def p_expression_group(p): + "expression : '(' expression ')'" + p[0] = p[2] + +def p_expression_number(p): + "expression : NUMBER" + p[0] = p[1] + +def p_expression_name(p): + "expression : NAME" + try: + p[0] = names[p[1]] + except LookupError: + print("Undefined name '%s'" % p[1]) + p[0] = 0 + +def p_error(p): + if p: + print("Syntax error at '%s'" % p.value) + else: + print("Syntax error at EOF") + +import ply.yacc as yacc +yacc.yacc() + +import logging +logging.basicConfig( + level=logging.INFO, + filename="parselog.txt" +) + +while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + if not s: continue + yacc.parse(s,debug=logging.getLogger()) diff --git a/simulators/gem5/ext/ply/example/classcalc/calc.py b/simulators/gem5/ext/ply/example/classcalc/calc.py new file mode 100755 index 00000000..bf0d065e --- /dev/null +++ b/simulators/gem5/ext/ply/example/classcalc/calc.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +# ----------------------------------------------------------------------------- +# calc.py +# +# A simple calculator with variables. This is from O'Reilly's +# "Lex and Yacc", p. 63. +# +# Class-based example contributed to PLY by David McNab +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +import ply.lex as lex +import ply.yacc as yacc +import os + +class Parser: + """ + Base class for a lexer/parser that has the rules defined as methods + """ + tokens = () + precedence = () + + def __init__(self, **kw): + self.debug = kw.get('debug', 0) + self.names = { } + try: + modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__ + except: + modname = "parser"+"_"+self.__class__.__name__ + self.debugfile = modname + ".dbg" + self.tabmodule = modname + "_" + "parsetab" + #print self.debugfile, self.tabmodule + + # Build the lexer and parser + lex.lex(module=self, debug=self.debug) + yacc.yacc(module=self, + debug=self.debug, + debugfile=self.debugfile, + tabmodule=self.tabmodule) + + def run(self): + while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + if not s: continue + yacc.parse(s) + + +class Calc(Parser): + + tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + + # Tokens + + t_PLUS = r'\+' + t_MINUS = r'-' + t_EXP = r'\*\*' + t_TIMES = r'\*' + t_DIVIDE = r'/' + t_EQUALS = r'=' + t_LPAREN = r'\(' + t_RPAREN = r'\)' + t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + + def t_NUMBER(self, t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + #print "parsed number %s" % repr(t.value) + return t + + t_ignore = " \t" + + def t_newline(self, t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + + def t_error(self, t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + + # Parsing rules + + precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('left', 'EXP'), + ('right','UMINUS'), + ) + + def p_statement_assign(self, p): + 'statement : NAME EQUALS expression' + self.names[p[1]] = p[3] + + def p_statement_expr(self, p): + 'statement : expression' + print(p[1]) + + def p_expression_binop(self, p): + """ + expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression + | expression EXP expression + """ + #print [repr(p[i]) for i in range(0,4)] + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + elif p[2] == '**': p[0] = p[1] ** p[3] + + def p_expression_uminus(self, p): + 'expression : MINUS expression %prec UMINUS' + p[0] = -p[2] + + def p_expression_group(self, p): + 'expression : LPAREN expression RPAREN' + p[0] = p[2] + + def p_expression_number(self, p): + 'expression : NUMBER' + p[0] = p[1] + + def p_expression_name(self, p): + 'expression : NAME' + try: + p[0] = self.names[p[1]] + except LookupError: + print("Undefined name '%s'" % p[1]) + p[0] = 0 + + def p_error(self, p): + if p: + print("Syntax error at '%s'" % p.value) + else: + print("Syntax error at EOF") + +if __name__ == '__main__': + calc = Calc() + calc.run() diff --git a/simulators/gem5/ext/ply/example/cleanup.sh b/simulators/gem5/ext/ply/example/cleanup.sh new file mode 100755 index 00000000..3e115f41 --- /dev/null +++ b/simulators/gem5/ext/ply/example/cleanup.sh @@ -0,0 +1,2 @@ +#!/bin/sh +rm -f */*.pyc */parsetab.py */parser.out */*~ */*.class diff --git a/simulators/gem5/ext/ply/example/closurecalc/calc.py b/simulators/gem5/ext/ply/example/closurecalc/calc.py new file mode 100644 index 00000000..6598f584 --- /dev/null +++ b/simulators/gem5/ext/ply/example/closurecalc/calc.py @@ -0,0 +1,130 @@ +# ----------------------------------------------------------------------------- +# calc.py +# +# A calculator parser that makes use of closures. The function make_calculator() +# returns a function that accepts an input string and returns a result. All +# lexing rules, parsing rules, and internal state are held inside the function. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +# Make a calculator function + +def make_calculator(): + import ply.lex as lex + import ply.yacc as yacc + + # ------- Internal calculator state + + variables = { } # Dictionary of stored variables + + # ------- Calculator tokenizing rules + + tokens = ( + 'NAME','NUMBER', + ) + + literals = ['=','+','-','*','/', '(',')'] + + t_ignore = " \t" + + t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + + def t_NUMBER(t): + r'\d+' + t.value = int(t.value) + return t + + def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + + def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + + # Build the lexer + lexer = lex.lex() + + # ------- Calculator parsing rules + + precedence = ( + ('left','+','-'), + ('left','*','/'), + ('right','UMINUS'), + ) + + def p_statement_assign(p): + 'statement : NAME "=" expression' + variables[p[1]] = p[3] + p[0] = None + + def p_statement_expr(p): + 'statement : expression' + p[0] = p[1] + + def p_expression_binop(p): + '''expression : expression '+' expression + | expression '-' expression + | expression '*' expression + | expression '/' expression''' + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + + def p_expression_uminus(p): + "expression : '-' expression %prec UMINUS" + p[0] = -p[2] + + def p_expression_group(p): + "expression : '(' expression ')'" + p[0] = p[2] + + def p_expression_number(p): + "expression : NUMBER" + p[0] = p[1] + + def p_expression_name(p): + "expression : NAME" + try: + p[0] = variables[p[1]] + except LookupError: + print("Undefined name '%s'" % p[1]) + p[0] = 0 + + def p_error(p): + if p: + print("Syntax error at '%s'" % p.value) + else: + print("Syntax error at EOF") + + + # Build the parser + parser = yacc.yacc() + + # ------- Input function + + def input(text): + result = parser.parse(text,lexer=lexer) + return result + + return input + +# Make a calculator object and use it +calc = make_calculator() + +while True: + try: + s = raw_input("calc > ") + except EOFError: + break + r = calc(s) + if r: + print(r) + + diff --git a/simulators/gem5/ext/ply/example/hedit/hedit.py b/simulators/gem5/ext/ply/example/hedit/hedit.py new file mode 100644 index 00000000..2e80675f --- /dev/null +++ b/simulators/gem5/ext/ply/example/hedit/hedit.py @@ -0,0 +1,48 @@ +# ----------------------------------------------------------------------------- +# hedit.py +# +# Paring of Fortran H Edit descriptions (Contributed by Pearu Peterson) +# +# These tokens can't be easily tokenized because they are of the following +# form: +# +# nHc1...cn +# +# where n is a positive integer and c1 ... cn are characters. +# +# This example shows how to modify the state of the lexer to parse +# such tokens +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + + +tokens = ( + 'H_EDIT_DESCRIPTOR', + ) + +# Tokens +t_ignore = " \t\n" + +def t_H_EDIT_DESCRIPTOR(t): + r"\d+H.*" # This grabs all of the remaining text + i = t.value.index('H') + n = eval(t.value[:i]) + + # Adjust the tokenizing position + t.lexer.lexpos -= len(t.value) - (i+1+n) + + t.value = t.value[i+1:i+1+n] + return t + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex() +lex.runmain() + + diff --git a/simulators/gem5/ext/ply/example/newclasscalc/calc.py b/simulators/gem5/ext/ply/example/newclasscalc/calc.py new file mode 100755 index 00000000..a12e498b --- /dev/null +++ b/simulators/gem5/ext/ply/example/newclasscalc/calc.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python + +# ----------------------------------------------------------------------------- +# calc.py +# +# A simple calculator with variables. This is from O'Reilly's +# "Lex and Yacc", p. 63. +# +# Class-based example contributed to PLY by David McNab. +# +# Modified to use new-style classes. Test case. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +import ply.lex as lex +import ply.yacc as yacc +import os + +class Parser(object): + """ + Base class for a lexer/parser that has the rules defined as methods + """ + tokens = () + precedence = () + + + def __init__(self, **kw): + self.debug = kw.get('debug', 0) + self.names = { } + try: + modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__ + except: + modname = "parser"+"_"+self.__class__.__name__ + self.debugfile = modname + ".dbg" + self.tabmodule = modname + "_" + "parsetab" + #print self.debugfile, self.tabmodule + + # Build the lexer and parser + lex.lex(module=self, debug=self.debug) + yacc.yacc(module=self, + debug=self.debug, + debugfile=self.debugfile, + tabmodule=self.tabmodule) + + def run(self): + while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + if not s: continue + yacc.parse(s) + + +class Calc(Parser): + + tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + + # Tokens + + t_PLUS = r'\+' + t_MINUS = r'-' + t_EXP = r'\*\*' + t_TIMES = r'\*' + t_DIVIDE = r'/' + t_EQUALS = r'=' + t_LPAREN = r'\(' + t_RPAREN = r'\)' + t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + + def t_NUMBER(self, t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + #print "parsed number %s" % repr(t.value) + return t + + t_ignore = " \t" + + def t_newline(self, t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + + def t_error(self, t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + + # Parsing rules + + precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('left', 'EXP'), + ('right','UMINUS'), + ) + + def p_statement_assign(self, p): + 'statement : NAME EQUALS expression' + self.names[p[1]] = p[3] + + def p_statement_expr(self, p): + 'statement : expression' + print(p[1]) + + def p_expression_binop(self, p): + """ + expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression + | expression EXP expression + """ + #print [repr(p[i]) for i in range(0,4)] + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + elif p[2] == '**': p[0] = p[1] ** p[3] + + def p_expression_uminus(self, p): + 'expression : MINUS expression %prec UMINUS' + p[0] = -p[2] + + def p_expression_group(self, p): + 'expression : LPAREN expression RPAREN' + p[0] = p[2] + + def p_expression_number(self, p): + 'expression : NUMBER' + p[0] = p[1] + + def p_expression_name(self, p): + 'expression : NAME' + try: + p[0] = self.names[p[1]] + except LookupError: + print("Undefined name '%s'" % p[1]) + p[0] = 0 + + def p_error(self, p): + if p: + print("Syntax error at '%s'" % p.value) + else: + print("Syntax error at EOF") + +if __name__ == '__main__': + calc = Calc() + calc.run() diff --git a/simulators/gem5/ext/ply/example/optcalc/README b/simulators/gem5/ext/ply/example/optcalc/README new file mode 100644 index 00000000..53dd5fcd --- /dev/null +++ b/simulators/gem5/ext/ply/example/optcalc/README @@ -0,0 +1,9 @@ +An example showing how to use Python optimized mode. +To run: + + - First run 'python calc.py' + + - Then run 'python -OO calc.py' + +If working correctly, the second version should run the +same way. diff --git a/simulators/gem5/ext/ply/example/optcalc/calc.py b/simulators/gem5/ext/ply/example/optcalc/calc.py new file mode 100644 index 00000000..dd83351a --- /dev/null +++ b/simulators/gem5/ext/ply/example/optcalc/calc.py @@ -0,0 +1,119 @@ +# ----------------------------------------------------------------------------- +# calc.py +# +# A simple calculator with variables. This is from O'Reilly's +# "Lex and Yacc", p. 63. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex(optimize=1) + +# Parsing rules + +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + elif t[2] == '<': t[0] = t[1] < t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + if t: + print("Syntax error at '%s'" % t.value) + else: + print("Syntax error at EOF") + +import ply.yacc as yacc +yacc.yacc(optimize=1) + +while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + yacc.parse(s) + diff --git a/simulators/gem5/ext/ply/example/unicalc/calc.py b/simulators/gem5/ext/ply/example/unicalc/calc.py new file mode 100644 index 00000000..55fb48df --- /dev/null +++ b/simulators/gem5/ext/ply/example/unicalc/calc.py @@ -0,0 +1,117 @@ +# ----------------------------------------------------------------------------- +# calc.py +# +# A simple calculator with variables. This is from O'Reilly's +# "Lex and Yacc", p. 63. +# +# This example uses unicode strings for tokens, docstrings, and input. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = ur'\+' +t_MINUS = ur'-' +t_TIMES = ur'\*' +t_DIVIDE = ur'/' +t_EQUALS = ur'=' +t_LPAREN = ur'\(' +t_RPAREN = ur'\)' +t_NAME = ur'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + ur'\d+' + try: + t.value = int(t.value) + except ValueError: + print "Integer value too large", t.value + t.value = 0 + return t + +t_ignore = u" \t" + +def t_newline(t): + ur'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print "Illegal character '%s'" % t.value[0] + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex() + +# Parsing rules + +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(p): + 'statement : NAME EQUALS expression' + names[p[1]] = p[3] + +def p_statement_expr(p): + 'statement : expression' + print p[1] + +def p_expression_binop(p): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if p[2] == u'+' : p[0] = p[1] + p[3] + elif p[2] == u'-': p[0] = p[1] - p[3] + elif p[2] == u'*': p[0] = p[1] * p[3] + elif p[2] == u'/': p[0] = p[1] / p[3] + +def p_expression_uminus(p): + 'expression : MINUS expression %prec UMINUS' + p[0] = -p[2] + +def p_expression_group(p): + 'expression : LPAREN expression RPAREN' + p[0] = p[2] + +def p_expression_number(p): + 'expression : NUMBER' + p[0] = p[1] + +def p_expression_name(p): + 'expression : NAME' + try: + p[0] = names[p[1]] + except LookupError: + print "Undefined name '%s'" % p[1] + p[0] = 0 + +def p_error(p): + if p: + print "Syntax error at '%s'" % p.value + else: + print "Syntax error at EOF" + +import ply.yacc as yacc +yacc.yacc() + +while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + if not s: continue + yacc.parse(unicode(s)) diff --git a/simulators/gem5/ext/ply/example/yply/README b/simulators/gem5/ext/ply/example/yply/README new file mode 100644 index 00000000..bfadf364 --- /dev/null +++ b/simulators/gem5/ext/ply/example/yply/README @@ -0,0 +1,41 @@ +yply.py + +This example implements a program yply.py that converts a UNIX-yacc +specification file into a PLY-compatible program. To use, simply +run it like this: + + % python yply.py [-nocode] inputfile.y >myparser.py + +The output of this program is Python code. In the output, +any C code in the original file is included, but is commented out. +If you use the -nocode option, then all of the C code in the +original file is just discarded. + +To use the resulting grammer with PLY, you'll need to edit the +myparser.py file. Within this file, some stub code is included that +can be used to test the construction of the parsing tables. However, +you'll need to do more editing to make a workable parser. + +Disclaimer: This just an example I threw together in an afternoon. +It might have some bugs. However, it worked when I tried it on +a yacc-specified C++ parser containing 442 rules and 855 parsing +states. + +Comments: + +1. This example does not parse specification files meant for lex/flex. + You'll need to specify the tokenizer on your own. + +2. This example shows a number of interesting PLY features including + + - Parsing of literal text delimited by nested parentheses + - Some interaction between the parser and the lexer. + - Use of literals in the grammar specification + - One pass compilation. The program just emits the result, + there is no intermediate parse tree. + +3. This program could probably be cleaned up and enhanced a lot. + It would be great if someone wanted to work on this (hint). + +-Dave + diff --git a/simulators/gem5/ext/ply/example/yply/ylex.py b/simulators/gem5/ext/ply/example/yply/ylex.py new file mode 100644 index 00000000..84f2f7a7 --- /dev/null +++ b/simulators/gem5/ext/ply/example/yply/ylex.py @@ -0,0 +1,112 @@ +# lexer for yacc-grammars +# +# Author: David Beazley (dave@dabeaz.com) +# Date : October 2, 2006 + +import sys +sys.path.append("../..") + +from ply import * + +tokens = ( + 'LITERAL','SECTION','TOKEN','LEFT','RIGHT','PREC','START','TYPE','NONASSOC','UNION','CODE', + 'ID','QLITERAL','NUMBER', +) + +states = (('code','exclusive'),) + +literals = [ ';', ',', '<', '>', '|',':' ] +t_ignore = ' \t' + +t_TOKEN = r'%token' +t_LEFT = r'%left' +t_RIGHT = r'%right' +t_NONASSOC = r'%nonassoc' +t_PREC = r'%prec' +t_START = r'%start' +t_TYPE = r'%type' +t_UNION = r'%union' +t_ID = r'[a-zA-Z_][a-zA-Z_0-9]*' +t_QLITERAL = r'''(?P['"]).*?(?P=quote)''' +t_NUMBER = r'\d+' + +def t_SECTION(t): + r'%%' + if getattr(t.lexer,"lastsection",0): + t.value = t.lexer.lexdata[t.lexpos+2:] + t.lexer.lexpos = len(t.lexer.lexdata) + else: + t.lexer.lastsection = 0 + return t + +# Comments +def t_ccomment(t): + r'/\*(.|\n)*?\*/' + t.lexer.lineno += t.value.count('\n') + +t_ignore_cppcomment = r'//.*' + +def t_LITERAL(t): + r'%\{(.|\n)*?%\}' + t.lexer.lineno += t.value.count("\n") + return t + +def t_NEWLINE(t): + r'\n' + t.lexer.lineno += 1 + +def t_code(t): + r'\{' + t.lexer.codestart = t.lexpos + t.lexer.level = 1 + t.lexer.begin('code') + +def t_code_ignore_string(t): + r'\"([^\\\n]|(\\.))*?\"' + +def t_code_ignore_char(t): + r'\'([^\\\n]|(\\.))*?\'' + +def t_code_ignore_comment(t): + r'/\*(.|\n)*?\*/' + +def t_code_ignore_cppcom(t): + r'//.*' + +def t_code_lbrace(t): + r'\{' + t.lexer.level += 1 + +def t_code_rbrace(t): + r'\}' + t.lexer.level -= 1 + if t.lexer.level == 0: + t.type = 'CODE' + t.value = t.lexer.lexdata[t.lexer.codestart:t.lexpos+1] + t.lexer.begin('INITIAL') + t.lexer.lineno += t.value.count('\n') + return t + +t_code_ignore_nonspace = r'[^\s\}\'\"\{]+' +t_code_ignore_whitespace = r'\s+' +t_code_ignore = "" + +def t_code_error(t): + raise RuntimeError + +def t_error(t): + print "%d: Illegal character '%s'" % (t.lexer.lineno, t.value[0]) + print t.value + t.lexer.skip(1) + +lex.lex() + +if __name__ == '__main__': + lex.runmain() + + + + + + + diff --git a/simulators/gem5/ext/ply/example/yply/yparse.py b/simulators/gem5/ext/ply/example/yply/yparse.py new file mode 100644 index 00000000..ab5b8845 --- /dev/null +++ b/simulators/gem5/ext/ply/example/yply/yparse.py @@ -0,0 +1,217 @@ +# parser for Unix yacc-based grammars +# +# Author: David Beazley (dave@dabeaz.com) +# Date : October 2, 2006 + +import ylex +tokens = ylex.tokens + +from ply import * + +tokenlist = [] +preclist = [] + +emit_code = 1 + +def p_yacc(p): + '''yacc : defsection rulesection''' + +def p_defsection(p): + '''defsection : definitions SECTION + | SECTION''' + p.lexer.lastsection = 1 + print "tokens = ", repr(tokenlist) + print + print "precedence = ", repr(preclist) + print + print "# -------------- RULES ----------------" + print + +def p_rulesection(p): + '''rulesection : rules SECTION''' + + print "# -------------- RULES END ----------------" + print_code(p[2],0) + +def p_definitions(p): + '''definitions : definitions definition + | definition''' + +def p_definition_literal(p): + '''definition : LITERAL''' + print_code(p[1],0) + +def p_definition_start(p): + '''definition : START ID''' + print "start = '%s'" % p[2] + +def p_definition_token(p): + '''definition : toktype opttype idlist optsemi ''' + for i in p[3]: + if i[0] not in "'\"": + tokenlist.append(i) + if p[1] == '%left': + preclist.append(('left',) + tuple(p[3])) + elif p[1] == '%right': + preclist.append(('right',) + tuple(p[3])) + elif p[1] == '%nonassoc': + preclist.append(('nonassoc',)+ tuple(p[3])) + +def p_toktype(p): + '''toktype : TOKEN + | LEFT + | RIGHT + | NONASSOC''' + p[0] = p[1] + +def p_opttype(p): + '''opttype : '<' ID '>' + | empty''' + +def p_idlist(p): + '''idlist : idlist optcomma tokenid + | tokenid''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + p[1].append(p[3]) + +def p_tokenid(p): + '''tokenid : ID + | ID NUMBER + | QLITERAL + | QLITERAL NUMBER''' + p[0] = p[1] + +def p_optsemi(p): + '''optsemi : ';' + | empty''' + +def p_optcomma(p): + '''optcomma : ',' + | empty''' + +def p_definition_type(p): + '''definition : TYPE '<' ID '>' namelist optsemi''' + # type declarations are ignored + +def p_namelist(p): + '''namelist : namelist optcomma ID + | ID''' + +def p_definition_union(p): + '''definition : UNION CODE optsemi''' + # Union declarations are ignored + +def p_rules(p): + '''rules : rules rule + | rule''' + if len(p) == 2: + rule = p[1] + else: + rule = p[2] + + # Print out a Python equivalent of this rule + + embedded = [ ] # Embedded actions (a mess) + embed_count = 0 + + rulename = rule[0] + rulecount = 1 + for r in rule[1]: + # r contains one of the rule possibilities + print "def p_%s_%d(p):" % (rulename,rulecount) + prod = [] + prodcode = "" + for i in range(len(r)): + item = r[i] + if item[0] == '{': # A code block + if i == len(r) - 1: + prodcode = item + break + else: + # an embedded action + embed_name = "_embed%d_%s" % (embed_count,rulename) + prod.append(embed_name) + embedded.append((embed_name,item)) + embed_count += 1 + else: + prod.append(item) + print " '''%s : %s'''" % (rulename, " ".join(prod)) + # Emit code + print_code(prodcode,4) + print + rulecount += 1 + + for e,code in embedded: + print "def p_%s(p):" % e + print " '''%s : '''" % e + print_code(code,4) + print + +def p_rule(p): + '''rule : ID ':' rulelist ';' ''' + p[0] = (p[1],[p[3]]) + +def p_rule2(p): + '''rule : ID ':' rulelist morerules ';' ''' + p[4].insert(0,p[3]) + p[0] = (p[1],p[4]) + +def p_rule_empty(p): + '''rule : ID ':' ';' ''' + p[0] = (p[1],[[]]) + +def p_rule_empty2(p): + '''rule : ID ':' morerules ';' ''' + + p[3].insert(0,[]) + p[0] = (p[1],p[3]) + +def p_morerules(p): + '''morerules : morerules '|' rulelist + | '|' rulelist + | '|' ''' + + if len(p) == 2: + p[0] = [[]] + elif len(p) == 3: + p[0] = [p[2]] + else: + p[0] = p[1] + p[0].append(p[3]) + +# print "morerules", len(p), p[0] + +def p_rulelist(p): + '''rulelist : rulelist ruleitem + | ruleitem''' + + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + p[1].append(p[2]) + +def p_ruleitem(p): + '''ruleitem : ID + | QLITERAL + | CODE + | PREC''' + p[0] = p[1] + +def p_empty(p): + '''empty : ''' + +def p_error(p): + pass + +yacc.yacc(debug=0) + +def print_code(code,indent): + if not emit_code: return + codelines = code.splitlines() + for c in codelines: + print "%s# %s" % (" "*indent,c) + diff --git a/simulators/gem5/ext/ply/example/yply/yply.py b/simulators/gem5/ext/ply/example/yply/yply.py new file mode 100755 index 00000000..a4398171 --- /dev/null +++ b/simulators/gem5/ext/ply/example/yply/yply.py @@ -0,0 +1,53 @@ +#!/usr/local/bin/python +# yply.py +# +# Author: David Beazley (dave@dabeaz.com) +# Date : October 2, 2006 +# +# Converts a UNIX-yacc specification file into a PLY-compatible +# specification. To use, simply do this: +# +# % python yply.py [-nocode] inputfile.y >myparser.py +# +# The output of this program is Python code. In the output, +# any C code in the original file is included, but is commented. +# If you use the -nocode option, then all of the C code in the +# original file is discarded. +# +# Disclaimer: This just an example I threw together in an afternoon. +# It might have some bugs. However, it worked when I tried it on +# a yacc-specified C++ parser containing 442 rules and 855 parsing +# states. +# + +import sys +sys.path.insert(0,"../..") + +import ylex +import yparse + +from ply import * + +if len(sys.argv) == 1: + print "usage : yply.py [-nocode] inputfile" + raise SystemExit + +if len(sys.argv) == 3: + if sys.argv[1] == '-nocode': + yparse.emit_code = 0 + else: + print "Unknown option '%s'" % sys.argv[1] + raise SystemExit + filename = sys.argv[2] +else: + filename = sys.argv[1] + +yacc.parse(open(filename).read()) + +print """ +if __name__ == '__main__': + from ply import * + yacc.yacc() +""" + + diff --git a/simulators/gem5/ext/ply/ply/__init__.py b/simulators/gem5/ext/ply/ply/__init__.py new file mode 100644 index 00000000..853a9855 --- /dev/null +++ b/simulators/gem5/ext/ply/ply/__init__.py @@ -0,0 +1,4 @@ +# PLY package +# Author: David Beazley (dave@dabeaz.com) + +__all__ = ['lex','yacc'] diff --git a/simulators/gem5/ext/ply/ply/cpp.py b/simulators/gem5/ext/ply/ply/cpp.py new file mode 100644 index 00000000..39f9d47f --- /dev/null +++ b/simulators/gem5/ext/ply/ply/cpp.py @@ -0,0 +1,898 @@ +# ----------------------------------------------------------------------------- +# cpp.py +# +# Author: David Beazley (http://www.dabeaz.com) +# Copyright (C) 2007 +# All rights reserved +# +# This module implements an ANSI-C style lexical preprocessor for PLY. +# ----------------------------------------------------------------------------- +from __future__ import generators + +# ----------------------------------------------------------------------------- +# Default preprocessor lexer definitions. These tokens are enough to get +# a basic preprocessor working. Other modules may import these if they want +# ----------------------------------------------------------------------------- + +tokens = ( + 'CPP_ID','CPP_INTEGER', 'CPP_FLOAT', 'CPP_STRING', 'CPP_CHAR', 'CPP_WS', 'CPP_COMMENT', 'CPP_POUND','CPP_DPOUND' +) + +literals = "+-*/%|&~^<>=!?()[]{}.,;:\\\'\"" + +# Whitespace +def t_CPP_WS(t): + r'\s+' + t.lexer.lineno += t.value.count("\n") + return t + +t_CPP_POUND = r'\#' +t_CPP_DPOUND = r'\#\#' + +# Identifier +t_CPP_ID = r'[A-Za-z_][\w_]*' + +# Integer literal +def CPP_INTEGER(t): + r'(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU]|[lL]|[uU][lL]|[lL][uU])?)' + return t + +t_CPP_INTEGER = CPP_INTEGER + +# Floating literal +t_CPP_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' + +# String literal +def t_CPP_STRING(t): + r'\"([^\\\n]|(\\(.|\n)))*?\"' + t.lexer.lineno += t.value.count("\n") + return t + +# Character constant 'c' or L'c' +def t_CPP_CHAR(t): + r'(L)?\'([^\\\n]|(\\(.|\n)))*?\'' + t.lexer.lineno += t.value.count("\n") + return t + +# Comment +def t_CPP_COMMENT(t): + r'(/\*(.|\n)*?\*/)|(//.*?\n)' + t.lexer.lineno += t.value.count("\n") + return t + +def t_error(t): + t.type = t.value[0] + t.value = t.value[0] + t.lexer.skip(1) + return t + +import re +import copy +import time +import os.path + +# ----------------------------------------------------------------------------- +# trigraph() +# +# Given an input string, this function replaces all trigraph sequences. +# The following mapping is used: +# +# ??= # +# ??/ \ +# ??' ^ +# ??( [ +# ??) ] +# ??! | +# ??< { +# ??> } +# ??- ~ +# ----------------------------------------------------------------------------- + +_trigraph_pat = re.compile(r'''\?\?[=/\'\(\)\!<>\-]''') +_trigraph_rep = { + '=':'#', + '/':'\\', + "'":'^', + '(':'[', + ')':']', + '!':'|', + '<':'{', + '>':'}', + '-':'~' +} + +def trigraph(input): + return _trigraph_pat.sub(lambda g: _trigraph_rep[g.group()[-1]],input) + +# ------------------------------------------------------------------ +# Macro object +# +# This object holds information about preprocessor macros +# +# .name - Macro name (string) +# .value - Macro value (a list of tokens) +# .arglist - List of argument names +# .variadic - Boolean indicating whether or not variadic macro +# .vararg - Name of the variadic parameter +# +# When a macro is created, the macro replacement token sequence is +# pre-scanned and used to create patch lists that are later used +# during macro expansion +# ------------------------------------------------------------------ + +class Macro(object): + def __init__(self,name,value,arglist=None,variadic=False): + self.name = name + self.value = value + self.arglist = arglist + self.variadic = variadic + if variadic: + self.vararg = arglist[-1] + self.source = None + +# ------------------------------------------------------------------ +# Preprocessor object +# +# Object representing a preprocessor. Contains macro definitions, +# include directories, and other information +# ------------------------------------------------------------------ + +class Preprocessor(object): + def __init__(self,lexer=None): + if lexer is None: + lexer = lex.lexer + self.lexer = lexer + self.macros = { } + self.path = [] + self.temp_path = [] + + # Probe the lexer for selected tokens + self.lexprobe() + + tm = time.localtime() + self.define("__DATE__ \"%s\"" % time.strftime("%b %d %Y",tm)) + self.define("__TIME__ \"%s\"" % time.strftime("%H:%M:%S",tm)) + self.parser = None + + # ----------------------------------------------------------------------------- + # tokenize() + # + # Utility function. Given a string of text, tokenize into a list of tokens + # ----------------------------------------------------------------------------- + + def tokenize(self,text): + tokens = [] + self.lexer.input(text) + while True: + tok = self.lexer.token() + if not tok: break + tokens.append(tok) + return tokens + + # --------------------------------------------------------------------- + # error() + # + # Report a preprocessor error/warning of some kind + # ---------------------------------------------------------------------- + + def error(self,file,line,msg): + print >>sys.stderr,"%s:%d %s" % (file,line,msg) + + # ---------------------------------------------------------------------- + # lexprobe() + # + # This method probes the preprocessor lexer object to discover + # the token types of symbols that are important to the preprocessor. + # If this works right, the preprocessor will simply "work" + # with any suitable lexer regardless of how tokens have been named. + # ---------------------------------------------------------------------- + + def lexprobe(self): + + # Determine the token type for identifiers + self.lexer.input("identifier") + tok = self.lexer.token() + if not tok or tok.value != "identifier": + print "Couldn't determine identifier type" + else: + self.t_ID = tok.type + + # Determine the token type for integers + self.lexer.input("12345") + tok = self.lexer.token() + if not tok or int(tok.value) != 12345: + print "Couldn't determine integer type" + else: + self.t_INTEGER = tok.type + self.t_INTEGER_TYPE = type(tok.value) + + # Determine the token type for strings enclosed in double quotes + self.lexer.input("\"filename\"") + tok = self.lexer.token() + if not tok or tok.value != "\"filename\"": + print "Couldn't determine string type" + else: + self.t_STRING = tok.type + + # Determine the token type for whitespace--if any + self.lexer.input(" ") + tok = self.lexer.token() + if not tok or tok.value != " ": + self.t_SPACE = None + else: + self.t_SPACE = tok.type + + # Determine the token type for newlines + self.lexer.input("\n") + tok = self.lexer.token() + if not tok or tok.value != "\n": + self.t_NEWLINE = None + print "Couldn't determine token for newlines" + else: + self.t_NEWLINE = tok.type + + self.t_WS = (self.t_SPACE, self.t_NEWLINE) + + # Check for other characters used by the preprocessor + chars = [ '<','>','#','##','\\','(',')',',','.'] + for c in chars: + self.lexer.input(c) + tok = self.lexer.token() + if not tok or tok.value != c: + print "Unable to lex '%s' required for preprocessor" % c + + # ---------------------------------------------------------------------- + # add_path() + # + # Adds a search path to the preprocessor. + # ---------------------------------------------------------------------- + + def add_path(self,path): + self.path.append(path) + + # ---------------------------------------------------------------------- + # group_lines() + # + # Given an input string, this function splits it into lines. Trailing whitespace + # is removed. Any line ending with \ is grouped with the next line. This + # function forms the lowest level of the preprocessor---grouping into text into + # a line-by-line format. + # ---------------------------------------------------------------------- + + def group_lines(self,input): + lex = self.lexer.clone() + lines = [x.rstrip() for x in input.splitlines()] + for i in xrange(len(lines)): + j = i+1 + while lines[i].endswith('\\') and (j < len(lines)): + lines[i] = lines[i][:-1]+lines[j] + lines[j] = "" + j += 1 + + input = "\n".join(lines) + lex.input(input) + lex.lineno = 1 + + current_line = [] + while True: + tok = lex.token() + if not tok: + break + current_line.append(tok) + if tok.type in self.t_WS and '\n' in tok.value: + yield current_line + current_line = [] + + if current_line: + yield current_line + + # ---------------------------------------------------------------------- + # tokenstrip() + # + # Remove leading/trailing whitespace tokens from a token list + # ---------------------------------------------------------------------- + + def tokenstrip(self,tokens): + i = 0 + while i < len(tokens) and tokens[i].type in self.t_WS: + i += 1 + del tokens[:i] + i = len(tokens)-1 + while i >= 0 and tokens[i].type in self.t_WS: + i -= 1 + del tokens[i+1:] + return tokens + + + # ---------------------------------------------------------------------- + # collect_args() + # + # Collects comma separated arguments from a list of tokens. The arguments + # must be enclosed in parenthesis. Returns a tuple (tokencount,args,positions) + # where tokencount is the number of tokens consumed, args is a list of arguments, + # and positions is a list of integers containing the starting index of each + # argument. Each argument is represented by a list of tokens. + # + # When collecting arguments, leading and trailing whitespace is removed + # from each argument. + # + # This function properly handles nested parenthesis and commas---these do not + # define new arguments. + # ---------------------------------------------------------------------- + + def collect_args(self,tokenlist): + args = [] + positions = [] + current_arg = [] + nesting = 1 + tokenlen = len(tokenlist) + + # Search for the opening '('. + i = 0 + while (i < tokenlen) and (tokenlist[i].type in self.t_WS): + i += 1 + + if (i < tokenlen) and (tokenlist[i].value == '('): + positions.append(i+1) + else: + self.error(self.source,tokenlist[0].lineno,"Missing '(' in macro arguments") + return 0, [], [] + + i += 1 + + while i < tokenlen: + t = tokenlist[i] + if t.value == '(': + current_arg.append(t) + nesting += 1 + elif t.value == ')': + nesting -= 1 + if nesting == 0: + if current_arg: + args.append(self.tokenstrip(current_arg)) + positions.append(i) + return i+1,args,positions + current_arg.append(t) + elif t.value == ',' and nesting == 1: + args.append(self.tokenstrip(current_arg)) + positions.append(i+1) + current_arg = [] + else: + current_arg.append(t) + i += 1 + + # Missing end argument + self.error(self.source,tokenlist[-1].lineno,"Missing ')' in macro arguments") + return 0, [],[] + + # ---------------------------------------------------------------------- + # macro_prescan() + # + # Examine the macro value (token sequence) and identify patch points + # This is used to speed up macro expansion later on---we'll know + # right away where to apply patches to the value to form the expansion + # ---------------------------------------------------------------------- + + def macro_prescan(self,macro): + macro.patch = [] # Standard macro arguments + macro.str_patch = [] # String conversion expansion + macro.var_comma_patch = [] # Variadic macro comma patch + i = 0 + while i < len(macro.value): + if macro.value[i].type == self.t_ID and macro.value[i].value in macro.arglist: + argnum = macro.arglist.index(macro.value[i].value) + # Conversion of argument to a string + if i > 0 and macro.value[i-1].value == '#': + macro.value[i] = copy.copy(macro.value[i]) + macro.value[i].type = self.t_STRING + del macro.value[i-1] + macro.str_patch.append((argnum,i-1)) + continue + # Concatenation + elif (i > 0 and macro.value[i-1].value == '##'): + macro.patch.append(('c',argnum,i-1)) + del macro.value[i-1] + continue + elif ((i+1) < len(macro.value) and macro.value[i+1].value == '##'): + macro.patch.append(('c',argnum,i)) + i += 1 + continue + # Standard expansion + else: + macro.patch.append(('e',argnum,i)) + elif macro.value[i].value == '##': + if macro.variadic and (i > 0) and (macro.value[i-1].value == ',') and \ + ((i+1) < len(macro.value)) and (macro.value[i+1].type == self.t_ID) and \ + (macro.value[i+1].value == macro.vararg): + macro.var_comma_patch.append(i-1) + i += 1 + macro.patch.sort(key=lambda x: x[2],reverse=True) + + # ---------------------------------------------------------------------- + # macro_expand_args() + # + # Given a Macro and list of arguments (each a token list), this method + # returns an expanded version of a macro. The return value is a token sequence + # representing the replacement macro tokens + # ---------------------------------------------------------------------- + + def macro_expand_args(self,macro,args): + # Make a copy of the macro token sequence + rep = [copy.copy(_x) for _x in macro.value] + + # Make string expansion patches. These do not alter the length of the replacement sequence + + str_expansion = {} + for argnum, i in macro.str_patch: + if argnum not in str_expansion: + str_expansion[argnum] = ('"%s"' % "".join([x.value for x in args[argnum]])).replace("\\","\\\\") + rep[i] = copy.copy(rep[i]) + rep[i].value = str_expansion[argnum] + + # Make the variadic macro comma patch. If the variadic macro argument is empty, we get rid + comma_patch = False + if macro.variadic and not args[-1]: + for i in macro.var_comma_patch: + rep[i] = None + comma_patch = True + + # Make all other patches. The order of these matters. It is assumed that the patch list + # has been sorted in reverse order of patch location since replacements will cause the + # size of the replacement sequence to expand from the patch point. + + expanded = { } + for ptype, argnum, i in macro.patch: + # Concatenation. Argument is left unexpanded + if ptype == 'c': + rep[i:i+1] = args[argnum] + # Normal expansion. Argument is macro expanded first + elif ptype == 'e': + if argnum not in expanded: + expanded[argnum] = self.expand_macros(args[argnum]) + rep[i:i+1] = expanded[argnum] + + # Get rid of removed comma if necessary + if comma_patch: + rep = [_i for _i in rep if _i] + + return rep + + + # ---------------------------------------------------------------------- + # expand_macros() + # + # Given a list of tokens, this function performs macro expansion. + # The expanded argument is a dictionary that contains macros already + # expanded. This is used to prevent infinite recursion. + # ---------------------------------------------------------------------- + + def expand_macros(self,tokens,expanded=None): + if expanded is None: + expanded = {} + i = 0 + while i < len(tokens): + t = tokens[i] + if t.type == self.t_ID: + if t.value in self.macros and t.value not in expanded: + # Yes, we found a macro match + expanded[t.value] = True + + m = self.macros[t.value] + if not m.arglist: + # A simple macro + ex = self.expand_macros([copy.copy(_x) for _x in m.value],expanded) + for e in ex: + e.lineno = t.lineno + tokens[i:i+1] = ex + i += len(ex) + else: + # A macro with arguments + j = i + 1 + while j < len(tokens) and tokens[j].type in self.t_WS: + j += 1 + if tokens[j].value == '(': + tokcount,args,positions = self.collect_args(tokens[j:]) + if not m.variadic and len(args) != len(m.arglist): + self.error(self.source,t.lineno,"Macro %s requires %d arguments" % (t.value,len(m.arglist))) + i = j + tokcount + elif m.variadic and len(args) < len(m.arglist)-1: + if len(m.arglist) > 2: + self.error(self.source,t.lineno,"Macro %s must have at least %d arguments" % (t.value, len(m.arglist)-1)) + else: + self.error(self.source,t.lineno,"Macro %s must have at least %d argument" % (t.value, len(m.arglist)-1)) + i = j + tokcount + else: + if m.variadic: + if len(args) == len(m.arglist)-1: + args.append([]) + else: + args[len(m.arglist)-1] = tokens[j+positions[len(m.arglist)-1]:j+tokcount-1] + del args[len(m.arglist):] + + # Get macro replacement text + rep = self.macro_expand_args(m,args) + rep = self.expand_macros(rep,expanded) + for r in rep: + r.lineno = t.lineno + tokens[i:j+tokcount] = rep + i += len(rep) + del expanded[t.value] + continue + elif t.value == '__LINE__': + t.type = self.t_INTEGER + t.value = self.t_INTEGER_TYPE(t.lineno) + + i += 1 + return tokens + + # ---------------------------------------------------------------------- + # evalexpr() + # + # Evaluate an expression token sequence for the purposes of evaluating + # integral expressions. + # ---------------------------------------------------------------------- + + def evalexpr(self,tokens): + # tokens = tokenize(line) + # Search for defined macros + i = 0 + while i < len(tokens): + if tokens[i].type == self.t_ID and tokens[i].value == 'defined': + j = i + 1 + needparen = False + result = "0L" + while j < len(tokens): + if tokens[j].type in self.t_WS: + j += 1 + continue + elif tokens[j].type == self.t_ID: + if tokens[j].value in self.macros: + result = "1L" + else: + result = "0L" + if not needparen: break + elif tokens[j].value == '(': + needparen = True + elif tokens[j].value == ')': + break + else: + self.error(self.source,tokens[i].lineno,"Malformed defined()") + j += 1 + tokens[i].type = self.t_INTEGER + tokens[i].value = self.t_INTEGER_TYPE(result) + del tokens[i+1:j+1] + i += 1 + tokens = self.expand_macros(tokens) + for i,t in enumerate(tokens): + if t.type == self.t_ID: + tokens[i] = copy.copy(t) + tokens[i].type = self.t_INTEGER + tokens[i].value = self.t_INTEGER_TYPE("0L") + elif t.type == self.t_INTEGER: + tokens[i] = copy.copy(t) + # Strip off any trailing suffixes + tokens[i].value = str(tokens[i].value) + while tokens[i].value[-1] not in "0123456789abcdefABCDEF": + tokens[i].value = tokens[i].value[:-1] + + expr = "".join([str(x.value) for x in tokens]) + expr = expr.replace("&&"," and ") + expr = expr.replace("||"," or ") + expr = expr.replace("!"," not ") + try: + result = eval(expr) + except StandardError: + self.error(self.source,tokens[0].lineno,"Couldn't evaluate expression") + result = 0 + return result + + # ---------------------------------------------------------------------- + # parsegen() + # + # Parse an input string/ + # ---------------------------------------------------------------------- + def parsegen(self,input,source=None): + + # Replace trigraph sequences + t = trigraph(input) + lines = self.group_lines(t) + + if not source: + source = "" + + self.define("__FILE__ \"%s\"" % source) + + self.source = source + chunk = [] + enable = True + iftrigger = False + ifstack = [] + + for x in lines: + for i,tok in enumerate(x): + if tok.type not in self.t_WS: break + if tok.value == '#': + # Preprocessor directive + + for tok in x: + if tok in self.t_WS and '\n' in tok.value: + chunk.append(tok) + + dirtokens = self.tokenstrip(x[i+1:]) + if dirtokens: + name = dirtokens[0].value + args = self.tokenstrip(dirtokens[1:]) + else: + name = "" + args = [] + + if name == 'define': + if enable: + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + self.define(args) + elif name == 'include': + if enable: + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + oldfile = self.macros['__FILE__'] + for tok in self.include(args): + yield tok + self.macros['__FILE__'] = oldfile + self.source = source + elif name == 'undef': + if enable: + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + self.undef(args) + elif name == 'ifdef': + ifstack.append((enable,iftrigger)) + if enable: + if not args[0].value in self.macros: + enable = False + iftrigger = False + else: + iftrigger = True + elif name == 'ifndef': + ifstack.append((enable,iftrigger)) + if enable: + if args[0].value in self.macros: + enable = False + iftrigger = False + else: + iftrigger = True + elif name == 'if': + ifstack.append((enable,iftrigger)) + if enable: + result = self.evalexpr(args) + if not result: + enable = False + iftrigger = False + else: + iftrigger = True + elif name == 'elif': + if ifstack: + if ifstack[-1][0]: # We only pay attention if outer "if" allows this + if enable: # If already true, we flip enable False + enable = False + elif not iftrigger: # If False, but not triggered yet, we'll check expression + result = self.evalexpr(args) + if result: + enable = True + iftrigger = True + else: + self.error(self.source,dirtokens[0].lineno,"Misplaced #elif") + + elif name == 'else': + if ifstack: + if ifstack[-1][0]: + if enable: + enable = False + elif not iftrigger: + enable = True + iftrigger = True + else: + self.error(self.source,dirtokens[0].lineno,"Misplaced #else") + + elif name == 'endif': + if ifstack: + enable,iftrigger = ifstack.pop() + else: + self.error(self.source,dirtokens[0].lineno,"Misplaced #endif") + else: + # Unknown preprocessor directive + pass + + else: + # Normal text + if enable: + chunk.extend(x) + + for tok in self.expand_macros(chunk): + yield tok + chunk = [] + + # ---------------------------------------------------------------------- + # include() + # + # Implementation of file-inclusion + # ---------------------------------------------------------------------- + + def include(self,tokens): + # Try to extract the filename and then process an include file + if not tokens: + return + if tokens: + if tokens[0].value != '<' and tokens[0].type != self.t_STRING: + tokens = self.expand_macros(tokens) + + if tokens[0].value == '<': + # Include <...> + i = 1 + while i < len(tokens): + if tokens[i].value == '>': + break + i += 1 + else: + print "Malformed #include <...>" + return + filename = "".join([x.value for x in tokens[1:i]]) + path = self.path + [""] + self.temp_path + elif tokens[0].type == self.t_STRING: + filename = tokens[0].value[1:-1] + path = self.temp_path + [""] + self.path + else: + print "Malformed #include statement" + return + for p in path: + iname = os.path.join(p,filename) + try: + data = open(iname,"r").read() + dname = os.path.dirname(iname) + if dname: + self.temp_path.insert(0,dname) + for tok in self.parsegen(data,filename): + yield tok + if dname: + del self.temp_path[0] + break + except IOError,e: + pass + else: + print "Couldn't find '%s'" % filename + + # ---------------------------------------------------------------------- + # define() + # + # Define a new macro + # ---------------------------------------------------------------------- + + def define(self,tokens): + if isinstance(tokens,(str,unicode)): + tokens = self.tokenize(tokens) + + linetok = tokens + try: + name = linetok[0] + if len(linetok) > 1: + mtype = linetok[1] + else: + mtype = None + if not mtype: + m = Macro(name.value,[]) + self.macros[name.value] = m + elif mtype.type in self.t_WS: + # A normal macro + m = Macro(name.value,self.tokenstrip(linetok[2:])) + self.macros[name.value] = m + elif mtype.value == '(': + # A macro with arguments + tokcount, args, positions = self.collect_args(linetok[1:]) + variadic = False + for a in args: + if variadic: + print "No more arguments may follow a variadic argument" + break + astr = "".join([str(_i.value) for _i in a]) + if astr == "...": + variadic = True + a[0].type = self.t_ID + a[0].value = '__VA_ARGS__' + variadic = True + del a[1:] + continue + elif astr[-3:] == "..." and a[0].type == self.t_ID: + variadic = True + del a[1:] + # If, for some reason, "." is part of the identifier, strip off the name for the purposes + # of macro expansion + if a[0].value[-3:] == '...': + a[0].value = a[0].value[:-3] + continue + if len(a) > 1 or a[0].type != self.t_ID: + print "Invalid macro argument" + break + else: + mvalue = self.tokenstrip(linetok[1+tokcount:]) + i = 0 + while i < len(mvalue): + if i+1 < len(mvalue): + if mvalue[i].type in self.t_WS and mvalue[i+1].value == '##': + del mvalue[i] + continue + elif mvalue[i].value == '##' and mvalue[i+1].type in self.t_WS: + del mvalue[i+1] + i += 1 + m = Macro(name.value,mvalue,[x[0].value for x in args],variadic) + self.macro_prescan(m) + self.macros[name.value] = m + else: + print "Bad macro definition" + except LookupError: + print "Bad macro definition" + + # ---------------------------------------------------------------------- + # undef() + # + # Undefine a macro + # ---------------------------------------------------------------------- + + def undef(self,tokens): + id = tokens[0].value + try: + del self.macros[id] + except LookupError: + pass + + # ---------------------------------------------------------------------- + # parse() + # + # Parse input text. + # ---------------------------------------------------------------------- + def parse(self,input,source=None,ignore={}): + self.ignore = ignore + self.parser = self.parsegen(input,source) + + # ---------------------------------------------------------------------- + # token() + # + # Method to return individual tokens + # ---------------------------------------------------------------------- + def token(self): + try: + while True: + tok = self.parser.next() + if tok.type not in self.ignore: return tok + except StopIteration: + self.parser = None + return None + +if __name__ == '__main__': + import ply.lex as lex + lexer = lex.lex() + + # Run a preprocessor + import sys + f = open(sys.argv[1]) + input = f.read() + + p = Preprocessor(lexer) + p.parse(input,sys.argv[1]) + while True: + tok = p.token() + if not tok: break + print p.source, tok + + + + + + + + + + + diff --git a/simulators/gem5/ext/ply/ply/ctokens.py b/simulators/gem5/ext/ply/ply/ctokens.py new file mode 100644 index 00000000..dd5f102d --- /dev/null +++ b/simulators/gem5/ext/ply/ply/ctokens.py @@ -0,0 +1,133 @@ +# ---------------------------------------------------------------------- +# ctokens.py +# +# Token specifications for symbols in ANSI C and C++. This file is +# meant to be used as a library in other tokenizers. +# ---------------------------------------------------------------------- + +# Reserved words + +tokens = [ + # Literals (identifier, integer constant, float constant, string constant, char const) + 'ID', 'TYPEID', 'ICONST', 'FCONST', 'SCONST', 'CCONST', + + # Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=) + 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', + 'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT', + 'LOR', 'LAND', 'LNOT', + 'LT', 'LE', 'GT', 'GE', 'EQ', 'NE', + + # Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=) + 'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL', + 'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL', + + # Increment/decrement (++,--) + 'PLUSPLUS', 'MINUSMINUS', + + # Structure dereference (->) + 'ARROW', + + # Ternary operator (?) + 'TERNARY', + + # Delimeters ( ) [ ] { } , . ; : + 'LPAREN', 'RPAREN', + 'LBRACKET', 'RBRACKET', + 'LBRACE', 'RBRACE', + 'COMMA', 'PERIOD', 'SEMI', 'COLON', + + # Ellipsis (...) + 'ELLIPSIS', +] + +# Operators +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_MODULO = r'%' +t_OR = r'\|' +t_AND = r'&' +t_NOT = r'~' +t_XOR = r'\^' +t_LSHIFT = r'<<' +t_RSHIFT = r'>>' +t_LOR = r'\|\|' +t_LAND = r'&&' +t_LNOT = r'!' +t_LT = r'<' +t_GT = r'>' +t_LE = r'<=' +t_GE = r'>=' +t_EQ = r'==' +t_NE = r'!=' + +# Assignment operators + +t_EQUALS = r'=' +t_TIMESEQUAL = r'\*=' +t_DIVEQUAL = r'/=' +t_MODEQUAL = r'%=' +t_PLUSEQUAL = r'\+=' +t_MINUSEQUAL = r'-=' +t_LSHIFTEQUAL = r'<<=' +t_RSHIFTEQUAL = r'>>=' +t_ANDEQUAL = r'&=' +t_OREQUAL = r'\|=' +t_XOREQUAL = r'^=' + +# Increment/decrement +t_INCREMENT = r'\+\+' +t_DECREMENT = r'--' + +# -> +t_ARROW = r'->' + +# ? +t_TERNARY = r'\?' + +# Delimeters +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_LBRACKET = r'\[' +t_RBRACKET = r'\]' +t_LBRACE = r'\{' +t_RBRACE = r'\}' +t_COMMA = r',' +t_PERIOD = r'\.' +t_SEMI = r';' +t_COLON = r':' +t_ELLIPSIS = r'\.\.\.' + +# Identifiers +t_ID = r'[A-Za-z_][A-Za-z0-9_]*' + +# Integer literal +t_INTEGER = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?' + +# Floating literal +t_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' + +# String literal +t_STRING = r'\"([^\\\n]|(\\.))*?\"' + +# Character constant 'c' or L'c' +t_CHARACTER = r'(L)?\'([^\\\n]|(\\.))*?\'' + +# Comment (C-Style) +def t_COMMENT(t): + r'/\*(.|\n)*?\*/' + t.lexer.lineno += t.value.count('\n') + return t + +# Comment (C++-Style) +def t_CPPCOMMENT(t): + r'//.*\n' + t.lexer.lineno += 1 + return t + + + + + + diff --git a/simulators/gem5/ext/ply/ply/lex.py b/simulators/gem5/ext/ply/ply/lex.py new file mode 100644 index 00000000..4759d1b7 --- /dev/null +++ b/simulators/gem5/ext/ply/ply/lex.py @@ -0,0 +1,1057 @@ +# ----------------------------------------------------------------------------- +# ply: lex.py +# +# Copyright (C) 2001-2009, +# David M. Beazley (Dabeaz LLC) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the David Beazley or Dabeaz LLC may be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ----------------------------------------------------------------------------- + +__version__ = "3.2" +__tabversion__ = "3.2" # Version of table file used + +import re, sys, types, copy, os + +# This tuple contains known string types +try: + # Python 2.6 + StringTypes = (types.StringType, types.UnicodeType) +except AttributeError: + # Python 3.0 + StringTypes = (str, bytes) + +# Extract the code attribute of a function. Different implementations +# are for Python 2/3 compatibility. + +if sys.version_info[0] < 3: + def func_code(f): + return f.func_code +else: + def func_code(f): + return f.__code__ + +# This regular expression is used to match valid token names +_is_identifier = re.compile(r'^[a-zA-Z0-9_]+$') + +# Exception thrown when invalid token encountered and no default error +# handler is defined. + +class LexError(Exception): + def __init__(self,message,s): + self.args = (message,) + self.text = s + +# Token class. This class is used to represent the tokens produced. +class LexToken(object): + def __str__(self): + return "LexToken(%s,%r,%d,%d)" % (self.type,self.value,self.lineno,self.lexpos) + def __repr__(self): + return str(self) + +# This object is a stand-in for a logging object created by the +# logging module. + +class PlyLogger(object): + def __init__(self,f): + self.f = f + def critical(self,msg,*args,**kwargs): + self.f.write((msg % args) + "\n") + + def warning(self,msg,*args,**kwargs): + self.f.write("WARNING: "+ (msg % args) + "\n") + + def error(self,msg,*args,**kwargs): + self.f.write("ERROR: " + (msg % args) + "\n") + + info = critical + debug = critical + +# Null logger is used when no output is generated. Does nothing. +class NullLogger(object): + def __getattribute__(self,name): + return self + def __call__(self,*args,**kwargs): + return self + +# ----------------------------------------------------------------------------- +# === Lexing Engine === +# +# The following Lexer class implements the lexer runtime. There are only +# a few public methods and attributes: +# +# input() - Store a new string in the lexer +# token() - Get the next token +# clone() - Clone the lexer +# +# lineno - Current line number +# lexpos - Current position in the input string +# ----------------------------------------------------------------------------- + +class Lexer: + def __init__(self): + self.lexre = None # Master regular expression. This is a list of + # tuples (re,findex) where re is a compiled + # regular expression and findex is a list + # mapping regex group numbers to rules + self.lexretext = None # Current regular expression strings + self.lexstatere = {} # Dictionary mapping lexer states to master regexs + self.lexstateretext = {} # Dictionary mapping lexer states to regex strings + self.lexstaterenames = {} # Dictionary mapping lexer states to symbol names + self.lexstate = "INITIAL" # Current lexer state + self.lexstatestack = [] # Stack of lexer states + self.lexstateinfo = None # State information + self.lexstateignore = {} # Dictionary of ignored characters for each state + self.lexstateerrorf = {} # Dictionary of error functions for each state + self.lexreflags = 0 # Optional re compile flags + self.lexdata = None # Actual input data (as a string) + self.lexpos = 0 # Current position in input text + self.lexlen = 0 # Length of the input text + self.lexerrorf = None # Error rule (if any) + self.lextokens = None # List of valid tokens + self.lexignore = "" # Ignored characters + self.lexliterals = "" # Literal characters that can be passed through + self.lexmodule = None # Module + self.lineno = 1 # Current line number + self.lexoptimize = 0 # Optimized mode + + def clone(self,object=None): + c = copy.copy(self) + + # If the object parameter has been supplied, it means we are attaching the + # lexer to a new object. In this case, we have to rebind all methods in + # the lexstatere and lexstateerrorf tables. + + if object: + newtab = { } + for key, ritem in self.lexstatere.items(): + newre = [] + for cre, findex in ritem: + newfindex = [] + for f in findex: + if not f or not f[0]: + newfindex.append(f) + continue + newfindex.append((getattr(object,f[0].__name__),f[1])) + newre.append((cre,newfindex)) + newtab[key] = newre + c.lexstatere = newtab + c.lexstateerrorf = { } + for key, ef in self.lexstateerrorf.items(): + c.lexstateerrorf[key] = getattr(object,ef.__name__) + c.lexmodule = object + return c + + # ------------------------------------------------------------ + # writetab() - Write lexer information to a table file + # ------------------------------------------------------------ + def writetab(self,tabfile,outputdir=""): + if isinstance(tabfile,types.ModuleType): + return + basetabfilename = tabfile.split(".")[-1] + filename = os.path.join(outputdir,basetabfilename)+".py" + tf = open(filename,"w") + tf.write("# %s.py. This file automatically created by PLY (version %s). Don't edit!\n" % (tabfile,__version__)) + tf.write("_tabversion = %s\n" % repr(__version__)) + tf.write("_lextokens = %s\n" % repr(self.lextokens)) + tf.write("_lexreflags = %s\n" % repr(self.lexreflags)) + tf.write("_lexliterals = %s\n" % repr(self.lexliterals)) + tf.write("_lexstateinfo = %s\n" % repr(self.lexstateinfo)) + + tabre = { } + # Collect all functions in the initial state + initial = self.lexstatere["INITIAL"] + initialfuncs = [] + for part in initial: + for f in part[1]: + if f and f[0]: + initialfuncs.append(f) + + for key, lre in self.lexstatere.items(): + titem = [] + for i in range(len(lre)): + titem.append((self.lexstateretext[key][i],_funcs_to_names(lre[i][1],self.lexstaterenames[key][i]))) + tabre[key] = titem + + tf.write("_lexstatere = %s\n" % repr(tabre)) + tf.write("_lexstateignore = %s\n" % repr(self.lexstateignore)) + + taberr = { } + for key, ef in self.lexstateerrorf.items(): + if ef: + taberr[key] = ef.__name__ + else: + taberr[key] = None + tf.write("_lexstateerrorf = %s\n" % repr(taberr)) + tf.close() + + # ------------------------------------------------------------ + # readtab() - Read lexer information from a tab file + # ------------------------------------------------------------ + def readtab(self,tabfile,fdict): + if isinstance(tabfile,types.ModuleType): + lextab = tabfile + else: + if sys.version_info[0] < 3: + exec("import %s as lextab" % tabfile) + else: + env = { } + exec("import %s as lextab" % tabfile, env,env) + lextab = env['lextab'] + + if getattr(lextab,"_tabversion","0.0") != __version__: + raise ImportError("Inconsistent PLY version") + + self.lextokens = lextab._lextokens + self.lexreflags = lextab._lexreflags + self.lexliterals = lextab._lexliterals + self.lexstateinfo = lextab._lexstateinfo + self.lexstateignore = lextab._lexstateignore + self.lexstatere = { } + self.lexstateretext = { } + for key,lre in lextab._lexstatere.items(): + titem = [] + txtitem = [] + for i in range(len(lre)): + titem.append((re.compile(lre[i][0],lextab._lexreflags),_names_to_funcs(lre[i][1],fdict))) + txtitem.append(lre[i][0]) + self.lexstatere[key] = titem + self.lexstateretext[key] = txtitem + self.lexstateerrorf = { } + for key,ef in lextab._lexstateerrorf.items(): + self.lexstateerrorf[key] = fdict[ef] + self.begin('INITIAL') + + # ------------------------------------------------------------ + # input() - Push a new string into the lexer + # ------------------------------------------------------------ + def input(self,s): + # Pull off the first character to see if s looks like a string + c = s[:1] + if not isinstance(c,StringTypes): + raise ValueError("Expected a string") + self.lexdata = s + self.lexpos = 0 + self.lexlen = len(s) + + # ------------------------------------------------------------ + # begin() - Changes the lexing state + # ------------------------------------------------------------ + def begin(self,state): + if not state in self.lexstatere: + raise ValueError("Undefined state") + self.lexre = self.lexstatere[state] + self.lexretext = self.lexstateretext[state] + self.lexignore = self.lexstateignore.get(state,"") + self.lexerrorf = self.lexstateerrorf.get(state,None) + self.lexstate = state + + # ------------------------------------------------------------ + # push_state() - Changes the lexing state and saves old on stack + # ------------------------------------------------------------ + def push_state(self,state): + self.lexstatestack.append(self.lexstate) + self.begin(state) + + # ------------------------------------------------------------ + # pop_state() - Restores the previous state + # ------------------------------------------------------------ + def pop_state(self): + self.begin(self.lexstatestack.pop()) + + # ------------------------------------------------------------ + # current_state() - Returns the current lexing state + # ------------------------------------------------------------ + def current_state(self): + return self.lexstate + + # ------------------------------------------------------------ + # skip() - Skip ahead n characters + # ------------------------------------------------------------ + def skip(self,n): + self.lexpos += n + + # ------------------------------------------------------------ + # opttoken() - Return the next token from the Lexer + # + # Note: This function has been carefully implemented to be as fast + # as possible. Don't make changes unless you really know what + # you are doing + # ------------------------------------------------------------ + def token(self): + # Make local copies of frequently referenced attributes + lexpos = self.lexpos + lexlen = self.lexlen + lexignore = self.lexignore + lexdata = self.lexdata + + while lexpos < lexlen: + # This code provides some short-circuit code for whitespace, tabs, and other ignored characters + if lexdata[lexpos] in lexignore: + lexpos += 1 + continue + + # Look for a regular expression match + for lexre,lexindexfunc in self.lexre: + m = lexre.match(lexdata,lexpos) + if not m: continue + + # Create a token for return + tok = LexToken() + tok.value = m.group() + tok.lineno = self.lineno + tok.lexpos = lexpos + + i = m.lastindex + func,tok.type = lexindexfunc[i] + + if not func: + # If no token type was set, it's an ignored token + if tok.type: + self.lexpos = m.end() + return tok + else: + lexpos = m.end() + break + + lexpos = m.end() + + # If token is processed by a function, call it + + tok.lexer = self # Set additional attributes useful in token rules + self.lexmatch = m + self.lexpos = lexpos + + newtok = func(tok) + + # Every function must return a token, if nothing, we just move to next token + if not newtok: + lexpos = self.lexpos # This is here in case user has updated lexpos. + lexignore = self.lexignore # This is here in case there was a state change + break + + # Verify type of the token. If not in the token map, raise an error + if not self.lexoptimize: + if not newtok.type in self.lextokens: + raise LexError("%s:%d: Rule '%s' returned an unknown token type '%s'" % ( + func_code(func).co_filename, func_code(func).co_firstlineno, + func.__name__, newtok.type),lexdata[lexpos:]) + + return newtok + else: + # No match, see if in literals + if lexdata[lexpos] in self.lexliterals: + tok = LexToken() + tok.value = lexdata[lexpos] + tok.lineno = self.lineno + tok.type = tok.value + tok.lexpos = lexpos + self.lexpos = lexpos + 1 + return tok + + # No match. Call t_error() if defined. + if self.lexerrorf: + tok = LexToken() + tok.value = self.lexdata[lexpos:] + tok.lineno = self.lineno + tok.type = "error" + tok.lexer = self + tok.lexpos = lexpos + self.lexpos = lexpos + newtok = self.lexerrorf(tok) + if lexpos == self.lexpos: + # Error method didn't change text position at all. This is an error. + raise LexError("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:]) + lexpos = self.lexpos + if not newtok: continue + return newtok + + self.lexpos = lexpos + raise LexError("Illegal character '%s' at index %d" % (lexdata[lexpos],lexpos), lexdata[lexpos:]) + + self.lexpos = lexpos + 1 + if self.lexdata is None: + raise RuntimeError("No input string given with input()") + return None + + # Iterator interface + def __iter__(self): + return self + + def next(self): + t = self.token() + if t is None: + raise StopIteration + return t + + __next__ = next + +# ----------------------------------------------------------------------------- +# ==== Lex Builder === +# +# The functions and classes below are used to collect lexing information +# and build a Lexer object from it. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# get_caller_module_dict() +# +# This function returns a dictionary containing all of the symbols defined within +# a caller further down the call stack. This is used to get the environment +# associated with the yacc() call if none was provided. +# ----------------------------------------------------------------------------- + +def get_caller_module_dict(levels): + try: + raise RuntimeError + except RuntimeError: + e,b,t = sys.exc_info() + f = t.tb_frame + while levels > 0: + f = f.f_back + levels -= 1 + ldict = f.f_globals.copy() + if f.f_globals != f.f_locals: + ldict.update(f.f_locals) + + return ldict + +# ----------------------------------------------------------------------------- +# _funcs_to_names() +# +# Given a list of regular expression functions, this converts it to a list +# suitable for output to a table file +# ----------------------------------------------------------------------------- + +def _funcs_to_names(funclist,namelist): + result = [] + for f,name in zip(funclist,namelist): + if f and f[0]: + result.append((name, f[1])) + else: + result.append(f) + return result + +# ----------------------------------------------------------------------------- +# _names_to_funcs() +# +# Given a list of regular expression function names, this converts it back to +# functions. +# ----------------------------------------------------------------------------- + +def _names_to_funcs(namelist,fdict): + result = [] + for n in namelist: + if n and n[0]: + result.append((fdict[n[0]],n[1])) + else: + result.append(n) + return result + +# ----------------------------------------------------------------------------- +# _form_master_re() +# +# This function takes a list of all of the regex components and attempts to +# form the master regular expression. Given limitations in the Python re +# module, it may be necessary to break the master regex into separate expressions. +# ----------------------------------------------------------------------------- + +def _form_master_re(relist,reflags,ldict,toknames): + if not relist: return [] + regex = "|".join(relist) + try: + lexre = re.compile(regex,re.VERBOSE | reflags) + + # Build the index to function map for the matching engine + lexindexfunc = [ None ] * (max(lexre.groupindex.values())+1) + lexindexnames = lexindexfunc[:] + + for f,i in lexre.groupindex.items(): + handle = ldict.get(f,None) + if type(handle) in (types.FunctionType, types.MethodType): + lexindexfunc[i] = (handle,toknames[f]) + lexindexnames[i] = f + elif handle is not None: + lexindexnames[i] = f + if f.find("ignore_") > 0: + lexindexfunc[i] = (None,None) + else: + lexindexfunc[i] = (None, toknames[f]) + + return [(lexre,lexindexfunc)],[regex],[lexindexnames] + except Exception: + m = int(len(relist)/2) + if m == 0: m = 1 + llist, lre, lnames = _form_master_re(relist[:m],reflags,ldict,toknames) + rlist, rre, rnames = _form_master_re(relist[m:],reflags,ldict,toknames) + return llist+rlist, lre+rre, lnames+rnames + +# ----------------------------------------------------------------------------- +# def _statetoken(s,names) +# +# Given a declaration name s of the form "t_" and a dictionary whose keys are +# state names, this function returns a tuple (states,tokenname) where states +# is a tuple of state names and tokenname is the name of the token. For example, +# calling this with s = "t_foo_bar_SPAM" might return (('foo','bar'),'SPAM') +# ----------------------------------------------------------------------------- + +def _statetoken(s,names): + nonstate = 1 + parts = s.split("_") + for i in range(1,len(parts)): + if not parts[i] in names and parts[i] != 'ANY': break + if i > 1: + states = tuple(parts[1:i]) + else: + states = ('INITIAL',) + + if 'ANY' in states: + states = tuple(names) + + tokenname = "_".join(parts[i:]) + return (states,tokenname) + + +# ----------------------------------------------------------------------------- +# LexerReflect() +# +# This class represents information needed to build a lexer as extracted from a +# user's input file. +# ----------------------------------------------------------------------------- +class LexerReflect(object): + def __init__(self,ldict,log=None,reflags=0): + self.ldict = ldict + self.error_func = None + self.tokens = [] + self.reflags = reflags + self.stateinfo = { 'INITIAL' : 'inclusive'} + self.files = {} + self.error = 0 + + if log is None: + self.log = PlyLogger(sys.stderr) + else: + self.log = log + + # Get all of the basic information + def get_all(self): + self.get_tokens() + self.get_literals() + self.get_states() + self.get_rules() + + # Validate all of the information + def validate_all(self): + self.validate_tokens() + self.validate_literals() + self.validate_rules() + return self.error + + # Get the tokens map + def get_tokens(self): + tokens = self.ldict.get("tokens",None) + if not tokens: + self.log.error("No token list is defined") + self.error = 1 + return + + if not isinstance(tokens,(list, tuple)): + self.log.error("tokens must be a list or tuple") + self.error = 1 + return + + if not tokens: + self.log.error("tokens is empty") + self.error = 1 + return + + self.tokens = tokens + + # Validate the tokens + def validate_tokens(self): + terminals = {} + for n in self.tokens: + if not _is_identifier.match(n): + self.log.error("Bad token name '%s'",n) + self.error = 1 + if n in terminals: + self.log.warning("Token '%s' multiply defined", n) + terminals[n] = 1 + + # Get the literals specifier + def get_literals(self): + self.literals = self.ldict.get("literals","") + + # Validate literals + def validate_literals(self): + try: + for c in self.literals: + if not isinstance(c,StringTypes) or len(c) > 1: + self.log.error("Invalid literal %s. Must be a single character", repr(c)) + self.error = 1 + continue + + except TypeError: + self.log.error("Invalid literals specification. literals must be a sequence of characters") + self.error = 1 + + def get_states(self): + self.states = self.ldict.get("states",None) + # Build statemap + if self.states: + if not isinstance(self.states,(tuple,list)): + self.log.error("states must be defined as a tuple or list") + self.error = 1 + else: + for s in self.states: + if not isinstance(s,tuple) or len(s) != 2: + self.log.error("Invalid state specifier %s. Must be a tuple (statename,'exclusive|inclusive')",repr(s)) + self.error = 1 + continue + name, statetype = s + if not isinstance(name,StringTypes): + self.log.error("State name %s must be a string", repr(name)) + self.error = 1 + continue + if not (statetype == 'inclusive' or statetype == 'exclusive'): + self.log.error("State type for state %s must be 'inclusive' or 'exclusive'",name) + self.error = 1 + continue + if name in self.stateinfo: + self.log.error("State '%s' already defined",name) + self.error = 1 + continue + self.stateinfo[name] = statetype + + # Get all of the symbols with a t_ prefix and sort them into various + # categories (functions, strings, error functions, and ignore characters) + + def get_rules(self): + tsymbols = [f for f in self.ldict if f[:2] == 't_' ] + + # Now build up a list of functions and a list of strings + + self.toknames = { } # Mapping of symbols to token names + self.funcsym = { } # Symbols defined as functions + self.strsym = { } # Symbols defined as strings + self.ignore = { } # Ignore strings by state + self.errorf = { } # Error functions by state + + for s in self.stateinfo: + self.funcsym[s] = [] + self.strsym[s] = [] + + if len(tsymbols) == 0: + self.log.error("No rules of the form t_rulename are defined") + self.error = 1 + return + + for f in tsymbols: + t = self.ldict[f] + states, tokname = _statetoken(f,self.stateinfo) + self.toknames[f] = tokname + + if hasattr(t,"__call__"): + if tokname == 'error': + for s in states: + self.errorf[s] = t + elif tokname == 'ignore': + line = func_code(t).co_firstlineno + file = func_code(t).co_filename + self.log.error("%s:%d: Rule '%s' must be defined as a string",file,line,t.__name__) + self.error = 1 + else: + for s in states: + self.funcsym[s].append((f,t)) + elif isinstance(t, StringTypes): + if tokname == 'ignore': + for s in states: + self.ignore[s] = t + if "\\" in t: + self.log.warning("%s contains a literal backslash '\\'",f) + + elif tokname == 'error': + self.log.error("Rule '%s' must be defined as a function", f) + self.error = 1 + else: + for s in states: + self.strsym[s].append((f,t)) + else: + self.log.error("%s not defined as a function or string", f) + self.error = 1 + + # Sort the functions by line number + for f in self.funcsym.values(): + if sys.version_info[0] < 3: + f.sort(lambda x,y: cmp(func_code(x[1]).co_firstlineno,func_code(y[1]).co_firstlineno)) + else: + # Python 3.0 + f.sort(key=lambda x: func_code(x[1]).co_firstlineno) + + # Sort the strings by regular expression length + for s in self.strsym.values(): + if sys.version_info[0] < 3: + s.sort(lambda x,y: (len(x[1]) < len(y[1])) - (len(x[1]) > len(y[1]))) + else: + # Python 3.0 + s.sort(key=lambda x: len(x[1]),reverse=True) + + # Validate all of the t_rules collected + def validate_rules(self): + for state in self.stateinfo: + # Validate all rules defined by functions + + + + for fname, f in self.funcsym[state]: + line = func_code(f).co_firstlineno + file = func_code(f).co_filename + self.files[file] = 1 + + tokname = self.toknames[fname] + if isinstance(f, types.MethodType): + reqargs = 2 + else: + reqargs = 1 + nargs = func_code(f).co_argcount + if nargs > reqargs: + self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,f.__name__) + self.error = 1 + continue + + if nargs < reqargs: + self.log.error("%s:%d: Rule '%s' requires an argument", file,line,f.__name__) + self.error = 1 + continue + + if not f.__doc__: + self.log.error("%s:%d: No regular expression defined for rule '%s'",file,line,f.__name__) + self.error = 1 + continue + + try: + c = re.compile("(?P<%s>%s)" % (fname,f.__doc__), re.VERBOSE | self.reflags) + if c.match(""): + self.log.error("%s:%d: Regular expression for rule '%s' matches empty string", file,line,f.__name__) + self.error = 1 + except re.error: + _etype, e, _etrace = sys.exc_info() + self.log.error("%s:%d: Invalid regular expression for rule '%s'. %s", file,line,f.__name__,e) + if '#' in f.__doc__: + self.log.error("%s:%d. Make sure '#' in rule '%s' is escaped with '\\#'",file,line, f.__name__) + self.error = 1 + + # Validate all rules defined by strings + for name,r in self.strsym[state]: + tokname = self.toknames[name] + if tokname == 'error': + self.log.error("Rule '%s' must be defined as a function", name) + self.error = 1 + continue + + if not tokname in self.tokens and tokname.find("ignore_") < 0: + self.log.error("Rule '%s' defined for an unspecified token %s",name,tokname) + self.error = 1 + continue + + try: + c = re.compile("(?P<%s>%s)" % (name,r),re.VERBOSE | self.reflags) + if (c.match("")): + self.log.error("Regular expression for rule '%s' matches empty string",name) + self.error = 1 + except re.error: + _etype, e, _etrace = sys.exc_info() + self.log.error("Invalid regular expression for rule '%s'. %s",name,e) + if '#' in r: + self.log.error("Make sure '#' in rule '%s' is escaped with '\\#'",name) + self.error = 1 + + if not self.funcsym[state] and not self.strsym[state]: + self.log.error("No rules defined for state '%s'",state) + self.error = 1 + + # Validate the error function + efunc = self.errorf.get(state,None) + if efunc: + f = efunc + line = func_code(f).co_firstlineno + file = func_code(f).co_filename + self.files[file] = 1 + + if isinstance(f, types.MethodType): + reqargs = 2 + else: + reqargs = 1 + nargs = func_code(f).co_argcount + if nargs > reqargs: + self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,f.__name__) + self.error = 1 + + if nargs < reqargs: + self.log.error("%s:%d: Rule '%s' requires an argument", file,line,f.__name__) + self.error = 1 + + for f in self.files: + self.validate_file(f) + + + # ----------------------------------------------------------------------------- + # validate_file() + # + # This checks to see if there are duplicated t_rulename() functions or strings + # in the parser input file. This is done using a simple regular expression + # match on each line in the given file. + # ----------------------------------------------------------------------------- + + def validate_file(self,filename): + import os.path + base,ext = os.path.splitext(filename) + if ext != '.py': return # No idea what the file is. Return OK + + try: + f = open(filename) + lines = f.readlines() + f.close() + except IOError: + return # Couldn't find the file. Don't worry about it + + fre = re.compile(r'\s*def\s+(t_[a-zA-Z_0-9]*)\(') + sre = re.compile(r'\s*(t_[a-zA-Z_0-9]*)\s*=') + + counthash = { } + linen = 1 + for l in lines: + m = fre.match(l) + if not m: + m = sre.match(l) + if m: + name = m.group(1) + prev = counthash.get(name) + if not prev: + counthash[name] = linen + else: + self.log.error("%s:%d: Rule %s redefined. Previously defined on line %d",filename,linen,name,prev) + self.error = 1 + linen += 1 + +# ----------------------------------------------------------------------------- +# lex(module) +# +# Build all of the regular expression rules from definitions in the supplied module +# ----------------------------------------------------------------------------- +def lex(module=None,object=None,debug=0,optimize=0,lextab="lextab",reflags=0,nowarn=0,outputdir="", debuglog=None, errorlog=None): + global lexer + ldict = None + stateinfo = { 'INITIAL' : 'inclusive'} + lexobj = Lexer() + lexobj.lexoptimize = optimize + global token,input + + if errorlog is None: + errorlog = PlyLogger(sys.stderr) + + if debug: + if debuglog is None: + debuglog = PlyLogger(sys.stderr) + + # Get the module dictionary used for the lexer + if object: module = object + + if module: + _items = [(k,getattr(module,k)) for k in dir(module)] + ldict = dict(_items) + else: + ldict = get_caller_module_dict(2) + + # Collect parser information from the dictionary + linfo = LexerReflect(ldict,log=errorlog,reflags=reflags) + linfo.get_all() + if not optimize: + if linfo.validate_all(): + raise SyntaxError("Can't build lexer") + + if optimize and lextab: + try: + lexobj.readtab(lextab,ldict) + token = lexobj.token + input = lexobj.input + lexer = lexobj + return lexobj + + except ImportError: + pass + + # Dump some basic debugging information + if debug: + debuglog.info("lex: tokens = %r", linfo.tokens) + debuglog.info("lex: literals = %r", linfo.literals) + debuglog.info("lex: states = %r", linfo.stateinfo) + + # Build a dictionary of valid token names + lexobj.lextokens = { } + for n in linfo.tokens: + lexobj.lextokens[n] = 1 + + # Get literals specification + if isinstance(linfo.literals,(list,tuple)): + lexobj.lexliterals = type(linfo.literals[0])().join(linfo.literals) + else: + lexobj.lexliterals = linfo.literals + + # Get the stateinfo dictionary + stateinfo = linfo.stateinfo + + regexs = { } + # Build the master regular expressions + for state in stateinfo: + regex_list = [] + + # Add rules defined by functions first + for fname, f in linfo.funcsym[state]: + line = func_code(f).co_firstlineno + file = func_code(f).co_filename + regex_list.append("(?P<%s>%s)" % (fname,f.__doc__)) + if debug: + debuglog.info("lex: Adding rule %s -> '%s' (state '%s')",fname,f.__doc__, state) + + # Now add all of the simple rules + for name,r in linfo.strsym[state]: + regex_list.append("(?P<%s>%s)" % (name,r)) + if debug: + debuglog.info("lex: Adding rule %s -> '%s' (state '%s')",name,r, state) + + regexs[state] = regex_list + + # Build the master regular expressions + + if debug: + debuglog.info("lex: ==== MASTER REGEXS FOLLOW ====") + + for state in regexs: + lexre, re_text, re_names = _form_master_re(regexs[state],reflags,ldict,linfo.toknames) + lexobj.lexstatere[state] = lexre + lexobj.lexstateretext[state] = re_text + lexobj.lexstaterenames[state] = re_names + if debug: + for i in range(len(re_text)): + debuglog.info("lex: state '%s' : regex[%d] = '%s'",state, i, re_text[i]) + + # For inclusive states, we need to add the regular expressions from the INITIAL state + for state,stype in stateinfo.items(): + if state != "INITIAL" and stype == 'inclusive': + lexobj.lexstatere[state].extend(lexobj.lexstatere['INITIAL']) + lexobj.lexstateretext[state].extend(lexobj.lexstateretext['INITIAL']) + lexobj.lexstaterenames[state].extend(lexobj.lexstaterenames['INITIAL']) + + lexobj.lexstateinfo = stateinfo + lexobj.lexre = lexobj.lexstatere["INITIAL"] + lexobj.lexretext = lexobj.lexstateretext["INITIAL"] + + # Set up ignore variables + lexobj.lexstateignore = linfo.ignore + lexobj.lexignore = lexobj.lexstateignore.get("INITIAL","") + + # Set up error functions + lexobj.lexstateerrorf = linfo.errorf + lexobj.lexerrorf = linfo.errorf.get("INITIAL",None) + if not lexobj.lexerrorf: + errorlog.warning("No t_error rule is defined") + + # Check state information for ignore and error rules + for s,stype in stateinfo.items(): + if stype == 'exclusive': + if not s in linfo.errorf: + errorlog.warning("No error rule is defined for exclusive state '%s'", s) + if not s in linfo.ignore and lexobj.lexignore: + errorlog.warning("No ignore rule is defined for exclusive state '%s'", s) + elif stype == 'inclusive': + if not s in linfo.errorf: + linfo.errorf[s] = linfo.errorf.get("INITIAL",None) + if not s in linfo.ignore: + linfo.ignore[s] = linfo.ignore.get("INITIAL","") + + # Create global versions of the token() and input() functions + token = lexobj.token + input = lexobj.input + lexer = lexobj + + # If in optimize mode, we write the lextab + if lextab and optimize: + lexobj.writetab(lextab,outputdir) + + return lexobj + +# ----------------------------------------------------------------------------- +# runmain() +# +# This runs the lexer as a main program +# ----------------------------------------------------------------------------- + +def runmain(lexer=None,data=None): + if not data: + try: + filename = sys.argv[1] + f = open(filename) + data = f.read() + f.close() + except IndexError: + sys.stdout.write("Reading from standard input (type EOF to end):\n") + data = sys.stdin.read() + + if lexer: + _input = lexer.input + else: + _input = input + _input(data) + if lexer: + _token = lexer.token + else: + _token = token + + while 1: + tok = _token() + if not tok: break + sys.stdout.write("(%s,%r,%d,%d)\n" % (tok.type, tok.value, tok.lineno,tok.lexpos)) + +# ----------------------------------------------------------------------------- +# @TOKEN(regex) +# +# This decorator function can be used to set the regex expression on a function +# when its docstring might need to be set in an alternative way +# ----------------------------------------------------------------------------- + +def TOKEN(r): + def set_doc(f): + if hasattr(r,"__call__"): + f.__doc__ = r.__doc__ + else: + f.__doc__ = r + return f + return set_doc + +# Alternative spelling of the TOKEN decorator +Token = TOKEN + diff --git a/simulators/gem5/ext/ply/ply/yacc.py b/simulators/gem5/ext/ply/ply/yacc.py new file mode 100644 index 00000000..3bf6e8e4 --- /dev/null +++ b/simulators/gem5/ext/ply/ply/yacc.py @@ -0,0 +1,3276 @@ +# ----------------------------------------------------------------------------- +# ply: yacc.py +# +# Copyright (C) 2001-2009, +# David M. Beazley (Dabeaz LLC) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the David Beazley or Dabeaz LLC may be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ----------------------------------------------------------------------------- +# +# This implements an LR parser that is constructed from grammar rules defined +# as Python functions. The grammer is specified by supplying the BNF inside +# Python documentation strings. The inspiration for this technique was borrowed +# from John Aycock's Spark parsing system. PLY might be viewed as cross between +# Spark and the GNU bison utility. +# +# The current implementation is only somewhat object-oriented. The +# LR parser itself is defined in terms of an object (which allows multiple +# parsers to co-exist). However, most of the variables used during table +# construction are defined in terms of global variables. Users shouldn't +# notice unless they are trying to define multiple parsers at the same +# time using threads (in which case they should have their head examined). +# +# This implementation supports both SLR and LALR(1) parsing. LALR(1) +# support was originally implemented by Elias Ioup (ezioup@alumni.uchicago.edu), +# using the algorithm found in Aho, Sethi, and Ullman "Compilers: Principles, +# Techniques, and Tools" (The Dragon Book). LALR(1) has since been replaced +# by the more efficient DeRemer and Pennello algorithm. +# +# :::::::: WARNING ::::::: +# +# Construction of LR parsing tables is fairly complicated and expensive. +# To make this module run fast, a *LOT* of work has been put into +# optimization---often at the expensive of readability and what might +# consider to be good Python "coding style." Modify the code at your +# own risk! +# ---------------------------------------------------------------------------- + +__version__ = "3.2" +__tabversion__ = "3.2" # Table version + +#----------------------------------------------------------------------------- +# === User configurable parameters === +# +# Change these to modify the default behavior of yacc (if you wish) +#----------------------------------------------------------------------------- + +yaccdebug = 1 # Debugging mode. If set, yacc generates a + # a 'parser.out' file in the current directory + +debug_file = 'parser.out' # Default name of the debugging file +tab_module = 'parsetab' # Default name of the table module +default_lr = 'LALR' # Default LR table generation method + +error_count = 3 # Number of symbols that must be shifted to leave recovery mode + +yaccdevel = 0 # Set to True if developing yacc. This turns off optimized + # implementations of certain functions. + +resultlimit = 40 # Size limit of results when running in debug mode. + +pickle_protocol = 0 # Protocol to use when writing pickle files + +import re, types, sys, os.path + +# Compatibility function for python 2.6/3.0 +if sys.version_info[0] < 3: + def func_code(f): + return f.func_code +else: + def func_code(f): + return f.__code__ + +# Compatibility +try: + MAXINT = sys.maxint +except AttributeError: + MAXINT = sys.maxsize + +# Python 2.x/3.0 compatibility. +def load_ply_lex(): + if sys.version_info[0] < 3: + import lex + else: + import ply.lex as lex + return lex + +# This object is a stand-in for a logging object created by the +# logging module. PLY will use this by default to create things +# such as the parser.out file. If a user wants more detailed +# information, they can create their own logging object and pass +# it into PLY. + +class PlyLogger(object): + def __init__(self,f): + self.f = f + def debug(self,msg,*args,**kwargs): + self.f.write((msg % args) + "\n") + info = debug + + def warning(self,msg,*args,**kwargs): + self.f.write("WARNING: "+ (msg % args) + "\n") + + def error(self,msg,*args,**kwargs): + self.f.write("ERROR: " + (msg % args) + "\n") + + critical = debug + +# Null logger is used when no output is generated. Does nothing. +class NullLogger(object): + def __getattribute__(self,name): + return self + def __call__(self,*args,**kwargs): + return self + +# Exception raised for yacc-related errors +class YaccError(Exception): pass + +# Format the result message that the parser produces when running in debug mode. +def format_result(r): + repr_str = repr(r) + if '\n' in repr_str: repr_str = repr(repr_str) + if len(repr_str) > resultlimit: + repr_str = repr_str[:resultlimit]+" ..." + result = "<%s @ 0x%x> (%s)" % (type(r).__name__,id(r),repr_str) + return result + + +# Format stack entries when the parser is running in debug mode +def format_stack_entry(r): + repr_str = repr(r) + if '\n' in repr_str: repr_str = repr(repr_str) + if len(repr_str) < 16: + return repr_str + else: + return "<%s @ 0x%x>" % (type(r).__name__,id(r)) + +#----------------------------------------------------------------------------- +# === LR Parsing Engine === +# +# The following classes are used for the LR parser itself. These are not +# used during table construction and are independent of the actual LR +# table generation algorithm +#----------------------------------------------------------------------------- + +# This class is used to hold non-terminal grammar symbols during parsing. +# It normally has the following attributes set: +# .type = Grammar symbol type +# .value = Symbol value +# .lineno = Starting line number +# .endlineno = Ending line number (optional, set automatically) +# .lexpos = Starting lex position +# .endlexpos = Ending lex position (optional, set automatically) + +class YaccSymbol: + def __str__(self): return self.type + def __repr__(self): return str(self) + +# This class is a wrapper around the objects actually passed to each +# grammar rule. Index lookup and assignment actually assign the +# .value attribute of the underlying YaccSymbol object. +# The lineno() method returns the line number of a given +# item (or 0 if not defined). The linespan() method returns +# a tuple of (startline,endline) representing the range of lines +# for a symbol. The lexspan() method returns a tuple (lexpos,endlexpos) +# representing the range of positional information for a symbol. + +class YaccProduction: + def __init__(self,s,stack=None): + self.slice = s + self.stack = stack + self.lexer = None + self.parser= None + def __getitem__(self,n): + if n >= 0: return self.slice[n].value + else: return self.stack[n].value + + def __setitem__(self,n,v): + self.slice[n].value = v + + def __getslice__(self,i,j): + return [s.value for s in self.slice[i:j]] + + def __len__(self): + return len(self.slice) + + def lineno(self,n): + return getattr(self.slice[n],"lineno",0) + + def set_lineno(self,n,lineno): + self.slice[n].lineno = n + + def linespan(self,n): + startline = getattr(self.slice[n],"lineno",0) + endline = getattr(self.slice[n],"endlineno",startline) + return startline,endline + + def lexpos(self,n): + return getattr(self.slice[n],"lexpos",0) + + def lexspan(self,n): + startpos = getattr(self.slice[n],"lexpos",0) + endpos = getattr(self.slice[n],"endlexpos",startpos) + return startpos,endpos + + def error(self): + raise SyntaxError + + +# ----------------------------------------------------------------------------- +# == LRParser == +# +# The LR Parsing engine. +# ----------------------------------------------------------------------------- + +class LRParser: + def __init__(self,lrtab,errorf): + self.productions = lrtab.lr_productions + self.action = lrtab.lr_action + self.goto = lrtab.lr_goto + self.errorfunc = errorf + + def errok(self): + self.errorok = 1 + + def restart(self): + del self.statestack[:] + del self.symstack[:] + sym = YaccSymbol() + sym.type = '$end' + self.symstack.append(sym) + self.statestack.append(0) + + def parse(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None): + if debug or yaccdevel: + if isinstance(debug,int): + debug = PlyLogger(sys.stderr) + return self.parsedebug(input,lexer,debug,tracking,tokenfunc) + elif tracking: + return self.parseopt(input,lexer,debug,tracking,tokenfunc) + else: + return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc) + + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # parsedebug(). + # + # This is the debugging enabled version of parse(). All changes made to the + # parsing engine should be made here. For the non-debugging version, + # copy this code to a method parseopt() and delete all of the sections + # enclosed in: + # + # #--! DEBUG + # statements + # #--! DEBUG + # + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + def parsedebug(self,input=None,lexer=None,debug=None,tracking=0,tokenfunc=None): + lookahead = None # Current lookahead symbol + lookaheadstack = [ ] # Stack of lookahead symbols + actions = self.action # Local reference to action table (to avoid lookup on self.) + goto = self.goto # Local reference to goto table (to avoid lookup on self.) + prod = self.productions # Local reference to production list (to avoid lookup on self.) + pslice = YaccProduction(None) # Production object passed to grammar rules + errorcount = 0 # Used during error recovery + + # --! DEBUG + debug.info("PLY: PARSE DEBUG START") + # --! DEBUG + + # If no lexer was given, we will try to use the lex module + if not lexer: + lex = load_ply_lex() + lexer = lex.lexer + + # Set up the lexer and parser objects on pslice + pslice.lexer = lexer + pslice.parser = self + + # If input was supplied, pass to lexer + if input is not None: + lexer.input(input) + + if tokenfunc is None: + # Tokenize function + get_token = lexer.token + else: + get_token = tokenfunc + + # Set up the state and symbol stacks + + statestack = [ ] # Stack of parsing states + self.statestack = statestack + symstack = [ ] # Stack of grammar symbols + self.symstack = symstack + + pslice.stack = symstack # Put in the production + errtoken = None # Err token + + # The start state is assumed to be (0,$end) + + statestack.append(0) + sym = YaccSymbol() + sym.type = "$end" + symstack.append(sym) + state = 0 + while 1: + # Get the next symbol on the input. If a lookahead symbol + # is already set, we just use that. Otherwise, we'll pull + # the next token off of the lookaheadstack or from the lexer + + # --! DEBUG + debug.debug('') + debug.debug('State : %s', state) + # --! DEBUG + + if not lookahead: + if not lookaheadstack: + lookahead = get_token() # Get the next token + else: + lookahead = lookaheadstack.pop() + if not lookahead: + lookahead = YaccSymbol() + lookahead.type = "$end" + + # --! DEBUG + debug.debug('Stack : %s', + ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()) + # --! DEBUG + + # Check the action table + ltype = lookahead.type + t = actions[state].get(ltype) + + if t is not None: + if t > 0: + # shift a symbol on the stack + statestack.append(t) + state = t + + # --! DEBUG + debug.debug("Action : Shift and goto state %s", t) + # --! DEBUG + + symstack.append(lookahead) + lookahead = None + + # Decrease error count on successful shift + if errorcount: errorcount -=1 + continue + + if t < 0: + # reduce a symbol on the stack, emit a production + p = prod[-t] + pname = p.name + plen = p.len + + # Get production function + sym = YaccSymbol() + sym.type = pname # Production name + sym.value = None + + # --! DEBUG + if plen: + debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, "["+",".join([format_stack_entry(_v.value) for _v in symstack[-plen:]])+"]",-t) + else: + debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, [],-t) + + # --! DEBUG + + if plen: + targ = symstack[-plen-1:] + targ[0] = sym + + # --! TRACKING + if tracking: + t1 = targ[1] + sym.lineno = t1.lineno + sym.lexpos = t1.lexpos + t1 = targ[-1] + sym.endlineno = getattr(t1,"endlineno",t1.lineno) + sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos) + + # --! TRACKING + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # below as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + del symstack[-plen:] + del statestack[-plen:] + p.callable(pslice) + # --! DEBUG + debug.info("Result : %s", format_result(pslice[0])) + # --! DEBUG + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) + symstack.pop() + statestack.pop() + state = statestack[-1] + sym.type = 'error' + lookahead = sym + errorcount = error_count + self.errorok = 0 + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else: + + # --! TRACKING + if tracking: + sym.lineno = lexer.lineno + sym.lexpos = lexer.lexpos + # --! TRACKING + + targ = [ sym ] + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # above as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + p.callable(pslice) + # --! DEBUG + debug.info("Result : %s", format_result(pslice[0])) + # --! DEBUG + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) + symstack.pop() + statestack.pop() + state = statestack[-1] + sym.type = 'error' + lookahead = sym + errorcount = error_count + self.errorok = 0 + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if t == 0: + n = symstack[-1] + result = getattr(n,"value",None) + # --! DEBUG + debug.info("Done : Returning %s", format_result(result)) + debug.info("PLY: PARSE DEBUG END") + # --! DEBUG + return result + + if t == None: + + # --! DEBUG + debug.error('Error : %s', + ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()) + # --! DEBUG + + # We have some kind of parsing error here. To handle + # this, we are going to push the current token onto + # the tokenstack and replace it with an 'error' token. + # If there are any synchronization rules, they may + # catch it. + # + # In addition to pushing the error token, we call call + # the user defined p_error() function if this is the + # first syntax error. This function is only called if + # errorcount == 0. + if errorcount == 0 or self.errorok: + errorcount = error_count + self.errorok = 0 + errtoken = lookahead + if errtoken.type == "$end": + errtoken = None # End of file! + if self.errorfunc: + global errok,token,restart + errok = self.errok # Set some special functions available in error recovery + token = get_token + restart = self.restart + if errtoken and not hasattr(errtoken,'lexer'): + errtoken.lexer = lexer + tok = self.errorfunc(errtoken) + del errok, token, restart # Delete special functions + + if self.errorok: + # User must have done some kind of panic + # mode recovery on their own. The + # returned token is the next lookahead + lookahead = tok + errtoken = None + continue + else: + if errtoken: + if hasattr(errtoken,"lineno"): lineno = lookahead.lineno + else: lineno = 0 + if lineno: + sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type)) + else: + sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type) + else: + sys.stderr.write("yacc: Parse error in input. EOF\n") + return + + else: + errorcount = error_count + + # case 1: the statestack only has 1 entry on it. If we're in this state, the + # entire parse has been rolled back and we're completely hosed. The token is + # discarded and we just keep going. + + if len(statestack) <= 1 and lookahead.type != "$end": + lookahead = None + errtoken = None + state = 0 + # Nuke the pushback stack + del lookaheadstack[:] + continue + + # case 2: the statestack has a couple of entries on it, but we're + # at the end of the file. nuke the top entry and generate an error token + + # Start nuking entries on the stack + if lookahead.type == "$end": + # Whoa. We're really hosed here. Bail out + return + + if lookahead.type != 'error': + sym = symstack[-1] + if sym.type == 'error': + # Hmmm. Error is on top of stack, we'll just nuke input + # symbol and continue + lookahead = None + continue + t = YaccSymbol() + t.type = 'error' + if hasattr(lookahead,"lineno"): + t.lineno = lookahead.lineno + t.value = lookahead + lookaheadstack.append(lookahead) + lookahead = t + else: + symstack.pop() + statestack.pop() + state = statestack[-1] # Potential bug fix + + continue + + # Call an error function here + raise RuntimeError("yacc: internal parser error!!!\n") + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # parseopt(). + # + # Optimized version of parse() method. DO NOT EDIT THIS CODE DIRECTLY. + # Edit the debug version above, then copy any modifications to the method + # below while removing #--! DEBUG sections. + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + + def parseopt(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None): + lookahead = None # Current lookahead symbol + lookaheadstack = [ ] # Stack of lookahead symbols + actions = self.action # Local reference to action table (to avoid lookup on self.) + goto = self.goto # Local reference to goto table (to avoid lookup on self.) + prod = self.productions # Local reference to production list (to avoid lookup on self.) + pslice = YaccProduction(None) # Production object passed to grammar rules + errorcount = 0 # Used during error recovery + + # If no lexer was given, we will try to use the lex module + if not lexer: + lex = load_ply_lex() + lexer = lex.lexer + + # Set up the lexer and parser objects on pslice + pslice.lexer = lexer + pslice.parser = self + + # If input was supplied, pass to lexer + if input is not None: + lexer.input(input) + + if tokenfunc is None: + # Tokenize function + get_token = lexer.token + else: + get_token = tokenfunc + + # Set up the state and symbol stacks + + statestack = [ ] # Stack of parsing states + self.statestack = statestack + symstack = [ ] # Stack of grammar symbols + self.symstack = symstack + + pslice.stack = symstack # Put in the production + errtoken = None # Err token + + # The start state is assumed to be (0,$end) + + statestack.append(0) + sym = YaccSymbol() + sym.type = '$end' + symstack.append(sym) + state = 0 + while 1: + # Get the next symbol on the input. If a lookahead symbol + # is already set, we just use that. Otherwise, we'll pull + # the next token off of the lookaheadstack or from the lexer + + if not lookahead: + if not lookaheadstack: + lookahead = get_token() # Get the next token + else: + lookahead = lookaheadstack.pop() + if not lookahead: + lookahead = YaccSymbol() + lookahead.type = '$end' + + # Check the action table + ltype = lookahead.type + t = actions[state].get(ltype) + + if t is not None: + if t > 0: + # shift a symbol on the stack + statestack.append(t) + state = t + + symstack.append(lookahead) + lookahead = None + + # Decrease error count on successful shift + if errorcount: errorcount -=1 + continue + + if t < 0: + # reduce a symbol on the stack, emit a production + p = prod[-t] + pname = p.name + plen = p.len + + # Get production function + sym = YaccSymbol() + sym.type = pname # Production name + sym.value = None + + if plen: + targ = symstack[-plen-1:] + targ[0] = sym + + # --! TRACKING + if tracking: + t1 = targ[1] + sym.lineno = t1.lineno + sym.lexpos = t1.lexpos + t1 = targ[-1] + sym.endlineno = getattr(t1,"endlineno",t1.lineno) + sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos) + + # --! TRACKING + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # below as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + del symstack[-plen:] + del statestack[-plen:] + p.callable(pslice) + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) + symstack.pop() + statestack.pop() + state = statestack[-1] + sym.type = 'error' + lookahead = sym + errorcount = error_count + self.errorok = 0 + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else: + + # --! TRACKING + if tracking: + sym.lineno = lexer.lineno + sym.lexpos = lexer.lexpos + # --! TRACKING + + targ = [ sym ] + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # above as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + p.callable(pslice) + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) + symstack.pop() + statestack.pop() + state = statestack[-1] + sym.type = 'error' + lookahead = sym + errorcount = error_count + self.errorok = 0 + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if t == 0: + n = symstack[-1] + return getattr(n,"value",None) + + if t == None: + + # We have some kind of parsing error here. To handle + # this, we are going to push the current token onto + # the tokenstack and replace it with an 'error' token. + # If there are any synchronization rules, they may + # catch it. + # + # In addition to pushing the error token, we call call + # the user defined p_error() function if this is the + # first syntax error. This function is only called if + # errorcount == 0. + if errorcount == 0 or self.errorok: + errorcount = error_count + self.errorok = 0 + errtoken = lookahead + if errtoken.type == '$end': + errtoken = None # End of file! + if self.errorfunc: + global errok,token,restart + errok = self.errok # Set some special functions available in error recovery + token = get_token + restart = self.restart + if errtoken and not hasattr(errtoken,'lexer'): + errtoken.lexer = lexer + tok = self.errorfunc(errtoken) + del errok, token, restart # Delete special functions + + if self.errorok: + # User must have done some kind of panic + # mode recovery on their own. The + # returned token is the next lookahead + lookahead = tok + errtoken = None + continue + else: + if errtoken: + if hasattr(errtoken,"lineno"): lineno = lookahead.lineno + else: lineno = 0 + if lineno: + sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type)) + else: + sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type) + else: + sys.stderr.write("yacc: Parse error in input. EOF\n") + return + + else: + errorcount = error_count + + # case 1: the statestack only has 1 entry on it. If we're in this state, the + # entire parse has been rolled back and we're completely hosed. The token is + # discarded and we just keep going. + + if len(statestack) <= 1 and lookahead.type != '$end': + lookahead = None + errtoken = None + state = 0 + # Nuke the pushback stack + del lookaheadstack[:] + continue + + # case 2: the statestack has a couple of entries on it, but we're + # at the end of the file. nuke the top entry and generate an error token + + # Start nuking entries on the stack + if lookahead.type == '$end': + # Whoa. We're really hosed here. Bail out + return + + if lookahead.type != 'error': + sym = symstack[-1] + if sym.type == 'error': + # Hmmm. Error is on top of stack, we'll just nuke input + # symbol and continue + lookahead = None + continue + t = YaccSymbol() + t.type = 'error' + if hasattr(lookahead,"lineno"): + t.lineno = lookahead.lineno + t.value = lookahead + lookaheadstack.append(lookahead) + lookahead = t + else: + symstack.pop() + statestack.pop() + state = statestack[-1] # Potential bug fix + + continue + + # Call an error function here + raise RuntimeError("yacc: internal parser error!!!\n") + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # parseopt_notrack(). + # + # Optimized version of parseopt() with line number tracking removed. + # DO NOT EDIT THIS CODE DIRECTLY. Copy the optimized version and remove + # code in the #--! TRACKING sections + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + def parseopt_notrack(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None): + lookahead = None # Current lookahead symbol + lookaheadstack = [ ] # Stack of lookahead symbols + actions = self.action # Local reference to action table (to avoid lookup on self.) + goto = self.goto # Local reference to goto table (to avoid lookup on self.) + prod = self.productions # Local reference to production list (to avoid lookup on self.) + pslice = YaccProduction(None) # Production object passed to grammar rules + errorcount = 0 # Used during error recovery + + # If no lexer was given, we will try to use the lex module + if not lexer: + lex = load_ply_lex() + lexer = lex.lexer + + # Set up the lexer and parser objects on pslice + pslice.lexer = lexer + pslice.parser = self + + # If input was supplied, pass to lexer + if input is not None: + lexer.input(input) + + if tokenfunc is None: + # Tokenize function + get_token = lexer.token + else: + get_token = tokenfunc + + # Set up the state and symbol stacks + + statestack = [ ] # Stack of parsing states + self.statestack = statestack + symstack = [ ] # Stack of grammar symbols + self.symstack = symstack + + pslice.stack = symstack # Put in the production + errtoken = None # Err token + + # The start state is assumed to be (0,$end) + + statestack.append(0) + sym = YaccSymbol() + sym.type = '$end' + symstack.append(sym) + state = 0 + while 1: + # Get the next symbol on the input. If a lookahead symbol + # is already set, we just use that. Otherwise, we'll pull + # the next token off of the lookaheadstack or from the lexer + + if not lookahead: + if not lookaheadstack: + lookahead = get_token() # Get the next token + else: + lookahead = lookaheadstack.pop() + if not lookahead: + lookahead = YaccSymbol() + lookahead.type = '$end' + + # Check the action table + ltype = lookahead.type + t = actions[state].get(ltype) + + if t is not None: + if t > 0: + # shift a symbol on the stack + statestack.append(t) + state = t + + symstack.append(lookahead) + lookahead = None + + # Decrease error count on successful shift + if errorcount: errorcount -=1 + continue + + if t < 0: + # reduce a symbol on the stack, emit a production + p = prod[-t] + pname = p.name + plen = p.len + + # Get production function + sym = YaccSymbol() + sym.type = pname # Production name + sym.value = None + + if plen: + targ = symstack[-plen-1:] + targ[0] = sym + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # below as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + del symstack[-plen:] + del statestack[-plen:] + p.callable(pslice) + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) + symstack.pop() + statestack.pop() + state = statestack[-1] + sym.type = 'error' + lookahead = sym + errorcount = error_count + self.errorok = 0 + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else: + + targ = [ sym ] + + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # The code enclosed in this section is duplicated + # above as a performance optimization. Make sure + # changes get made in both locations. + + pslice.slice = targ + + try: + # Call the grammar rule with our special slice object + p.callable(pslice) + symstack.append(sym) + state = goto[statestack[-1]][pname] + statestack.append(state) + except SyntaxError: + # If an error was set. Enter error recovery state + lookaheadstack.append(lookahead) + symstack.pop() + statestack.pop() + state = statestack[-1] + sym.type = 'error' + lookahead = sym + errorcount = error_count + self.errorok = 0 + continue + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if t == 0: + n = symstack[-1] + return getattr(n,"value",None) + + if t == None: + + # We have some kind of parsing error here. To handle + # this, we are going to push the current token onto + # the tokenstack and replace it with an 'error' token. + # If there are any synchronization rules, they may + # catch it. + # + # In addition to pushing the error token, we call call + # the user defined p_error() function if this is the + # first syntax error. This function is only called if + # errorcount == 0. + if errorcount == 0 or self.errorok: + errorcount = error_count + self.errorok = 0 + errtoken = lookahead + if errtoken.type == '$end': + errtoken = None # End of file! + if self.errorfunc: + global errok,token,restart + errok = self.errok # Set some special functions available in error recovery + token = get_token + restart = self.restart + if errtoken and not hasattr(errtoken,'lexer'): + errtoken.lexer = lexer + tok = self.errorfunc(errtoken) + del errok, token, restart # Delete special functions + + if self.errorok: + # User must have done some kind of panic + # mode recovery on their own. The + # returned token is the next lookahead + lookahead = tok + errtoken = None + continue + else: + if errtoken: + if hasattr(errtoken,"lineno"): lineno = lookahead.lineno + else: lineno = 0 + if lineno: + sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type)) + else: + sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type) + else: + sys.stderr.write("yacc: Parse error in input. EOF\n") + return + + else: + errorcount = error_count + + # case 1: the statestack only has 1 entry on it. If we're in this state, the + # entire parse has been rolled back and we're completely hosed. The token is + # discarded and we just keep going. + + if len(statestack) <= 1 and lookahead.type != '$end': + lookahead = None + errtoken = None + state = 0 + # Nuke the pushback stack + del lookaheadstack[:] + continue + + # case 2: the statestack has a couple of entries on it, but we're + # at the end of the file. nuke the top entry and generate an error token + + # Start nuking entries on the stack + if lookahead.type == '$end': + # Whoa. We're really hosed here. Bail out + return + + if lookahead.type != 'error': + sym = symstack[-1] + if sym.type == 'error': + # Hmmm. Error is on top of stack, we'll just nuke input + # symbol and continue + lookahead = None + continue + t = YaccSymbol() + t.type = 'error' + if hasattr(lookahead,"lineno"): + t.lineno = lookahead.lineno + t.value = lookahead + lookaheadstack.append(lookahead) + lookahead = t + else: + symstack.pop() + statestack.pop() + state = statestack[-1] # Potential bug fix + + continue + + # Call an error function here + raise RuntimeError("yacc: internal parser error!!!\n") + +# ----------------------------------------------------------------------------- +# === Grammar Representation === +# +# The following functions, classes, and variables are used to represent and +# manipulate the rules that make up a grammar. +# ----------------------------------------------------------------------------- + +import re + +# regex matching identifiers +_is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$') + +# ----------------------------------------------------------------------------- +# class Production: +# +# This class stores the raw information about a single production or grammar rule. +# A grammar rule refers to a specification such as this: +# +# expr : expr PLUS term +# +# Here are the basic attributes defined on all productions +# +# name - Name of the production. For example 'expr' +# prod - A list of symbols on the right side ['expr','PLUS','term'] +# prec - Production precedence level +# number - Production number. +# func - Function that executes on reduce +# file - File where production function is defined +# lineno - Line number where production function is defined +# +# The following attributes are defined or optional. +# +# len - Length of the production (number of symbols on right hand side) +# usyms - Set of unique symbols found in the production +# ----------------------------------------------------------------------------- + +class Production(object): + reduced = 0 + def __init__(self,number,name,prod,precedence=('right',0),func=None,file='',line=0): + self.name = name + self.prod = tuple(prod) + self.number = number + self.func = func + self.callable = None + self.file = file + self.line = line + self.prec = precedence + + # Internal settings used during table construction + + self.len = len(self.prod) # Length of the production + + # Create a list of unique production symbols used in the production + self.usyms = [ ] + for s in self.prod: + if s not in self.usyms: + self.usyms.append(s) + + # List of all LR items for the production + self.lr_items = [] + self.lr_next = None + + # Create a string representation + if self.prod: + self.str = "%s -> %s" % (self.name," ".join(self.prod)) + else: + self.str = "%s -> " % self.name + + def __str__(self): + return self.str + + def __repr__(self): + return "Production("+str(self)+")" + + def __len__(self): + return len(self.prod) + + def __nonzero__(self): + return 1 + + def __getitem__(self,index): + return self.prod[index] + + # Return the nth lr_item from the production (or None if at the end) + def lr_item(self,n): + if n > len(self.prod): return None + p = LRItem(self,n) + + # Precompute the list of productions immediately following. Hack. Remove later + try: + p.lr_after = Prodnames[p.prod[n+1]] + except (IndexError,KeyError): + p.lr_after = [] + try: + p.lr_before = p.prod[n-1] + except IndexError: + p.lr_before = None + + return p + + # Bind the production function name to a callable + def bind(self,pdict): + if self.func: + self.callable = pdict[self.func] + +# This class serves as a minimal standin for Production objects when +# reading table data from files. It only contains information +# actually used by the LR parsing engine, plus some additional +# debugging information. +class MiniProduction(object): + def __init__(self,str,name,len,func,file,line): + self.name = name + self.len = len + self.func = func + self.callable = None + self.file = file + self.line = line + self.str = str + def __str__(self): + return self.str + def __repr__(self): + return "MiniProduction(%s)" % self.str + + # Bind the production function name to a callable + def bind(self,pdict): + if self.func: + self.callable = pdict[self.func] + + +# ----------------------------------------------------------------------------- +# class LRItem +# +# This class represents a specific stage of parsing a production rule. For +# example: +# +# expr : expr . PLUS term +# +# In the above, the "." represents the current location of the parse. Here +# basic attributes: +# +# name - Name of the production. For example 'expr' +# prod - A list of symbols on the right side ['expr','.', 'PLUS','term'] +# number - Production number. +# +# lr_next Next LR item. Example, if we are ' expr -> expr . PLUS term' +# then lr_next refers to 'expr -> expr PLUS . term' +# lr_index - LR item index (location of the ".") in the prod list. +# lookaheads - LALR lookahead symbols for this item +# len - Length of the production (number of symbols on right hand side) +# lr_after - List of all productions that immediately follow +# lr_before - Grammar symbol immediately before +# ----------------------------------------------------------------------------- + +class LRItem(object): + def __init__(self,p,n): + self.name = p.name + self.prod = list(p.prod) + self.number = p.number + self.lr_index = n + self.lookaheads = { } + self.prod.insert(n,".") + self.prod = tuple(self.prod) + self.len = len(self.prod) + self.usyms = p.usyms + + def __str__(self): + if self.prod: + s = "%s -> %s" % (self.name," ".join(self.prod)) + else: + s = "%s -> " % self.name + return s + + def __repr__(self): + return "LRItem("+str(self)+")" + +# ----------------------------------------------------------------------------- +# rightmost_terminal() +# +# Return the rightmost terminal from a list of symbols. Used in add_production() +# ----------------------------------------------------------------------------- +def rightmost_terminal(symbols, terminals): + i = len(symbols) - 1 + while i >= 0: + if symbols[i] in terminals: + return symbols[i] + i -= 1 + return None + +# ----------------------------------------------------------------------------- +# === GRAMMAR CLASS === +# +# The following class represents the contents of the specified grammar along +# with various computed properties such as first sets, follow sets, LR items, etc. +# This data is used for critical parts of the table generation process later. +# ----------------------------------------------------------------------------- + +class GrammarError(YaccError): pass + +class Grammar(object): + def __init__(self,terminals): + self.Productions = [None] # A list of all of the productions. The first + # entry is always reserved for the purpose of + # building an augmented grammar + + self.Prodnames = { } # A dictionary mapping the names of nonterminals to a list of all + # productions of that nonterminal. + + self.Prodmap = { } # A dictionary that is only used to detect duplicate + # productions. + + self.Terminals = { } # A dictionary mapping the names of terminal symbols to a + # list of the rules where they are used. + + for term in terminals: + self.Terminals[term] = [] + + self.Terminals['error'] = [] + + self.Nonterminals = { } # A dictionary mapping names of nonterminals to a list + # of rule numbers where they are used. + + self.First = { } # A dictionary of precomputed FIRST(x) symbols + + self.Follow = { } # A dictionary of precomputed FOLLOW(x) symbols + + self.Precedence = { } # Precedence rules for each terminal. Contains tuples of the + # form ('right',level) or ('nonassoc', level) or ('left',level) + + self.UsedPrecedence = { } # Precedence rules that were actually used by the grammer. + # This is only used to provide error checking and to generate + # a warning about unused precedence rules. + + self.Start = None # Starting symbol for the grammar + + + def __len__(self): + return len(self.Productions) + + def __getitem__(self,index): + return self.Productions[index] + + # ----------------------------------------------------------------------------- + # set_precedence() + # + # Sets the precedence for a given terminal. assoc is the associativity such as + # 'left','right', or 'nonassoc'. level is a numeric level. + # + # ----------------------------------------------------------------------------- + + def set_precedence(self,term,assoc,level): + assert self.Productions == [None],"Must call set_precedence() before add_production()" + if term in self.Precedence: + raise GrammarError("Precedence already specified for terminal '%s'" % term) + if assoc not in ['left','right','nonassoc']: + raise GrammarError("Associativity must be one of 'left','right', or 'nonassoc'") + self.Precedence[term] = (assoc,level) + + # ----------------------------------------------------------------------------- + # add_production() + # + # Given an action function, this function assembles a production rule and + # computes its precedence level. + # + # The production rule is supplied as a list of symbols. For example, + # a rule such as 'expr : expr PLUS term' has a production name of 'expr' and + # symbols ['expr','PLUS','term']. + # + # Precedence is determined by the precedence of the right-most non-terminal + # or the precedence of a terminal specified by %prec. + # + # A variety of error checks are performed to make sure production symbols + # are valid and that %prec is used correctly. + # ----------------------------------------------------------------------------- + + def add_production(self,prodname,syms,func=None,file='',line=0): + + if prodname in self.Terminals: + raise GrammarError("%s:%d: Illegal rule name '%s'. Already defined as a token" % (file,line,prodname)) + if prodname == 'error': + raise GrammarError("%s:%d: Illegal rule name '%s'. error is a reserved word" % (file,line,prodname)) + if not _is_identifier.match(prodname): + raise GrammarError("%s:%d: Illegal rule name '%s'" % (file,line,prodname)) + + # Look for literal tokens + for n,s in enumerate(syms): + if s[0] in "'\"": + try: + c = eval(s) + if (len(c) > 1): + raise GrammarError("%s:%d: Literal token %s in rule '%s' may only be a single character" % (file,line,s, prodname)) + if not c in self.Terminals: + self.Terminals[c] = [] + syms[n] = c + continue + except SyntaxError: + pass + if not _is_identifier.match(s) and s != '%prec': + raise GrammarError("%s:%d: Illegal name '%s' in rule '%s'" % (file,line,s, prodname)) + + # Determine the precedence level + if '%prec' in syms: + if syms[-1] == '%prec': + raise GrammarError("%s:%d: Syntax error. Nothing follows %%prec" % (file,line)) + if syms[-2] != '%prec': + raise GrammarError("%s:%d: Syntax error. %%prec can only appear at the end of a grammar rule" % (file,line)) + precname = syms[-1] + prodprec = self.Precedence.get(precname,None) + if not prodprec: + raise GrammarError("%s:%d: Nothing known about the precedence of '%s'" % (file,line,precname)) + else: + self.UsedPrecedence[precname] = 1 + del syms[-2:] # Drop %prec from the rule + else: + # If no %prec, precedence is determined by the rightmost terminal symbol + precname = rightmost_terminal(syms,self.Terminals) + prodprec = self.Precedence.get(precname,('right',0)) + + # See if the rule is already in the rulemap + map = "%s -> %s" % (prodname,syms) + if map in self.Prodmap: + m = self.Prodmap[map] + raise GrammarError("%s:%d: Duplicate rule %s. " % (file,line, m) + + "Previous definition at %s:%d" % (m.file, m.line)) + + # From this point on, everything is valid. Create a new Production instance + pnumber = len(self.Productions) + if not prodname in self.Nonterminals: + self.Nonterminals[prodname] = [ ] + + # Add the production number to Terminals and Nonterminals + for t in syms: + if t in self.Terminals: + self.Terminals[t].append(pnumber) + else: + if not t in self.Nonterminals: + self.Nonterminals[t] = [ ] + self.Nonterminals[t].append(pnumber) + + # Create a production and add it to the list of productions + p = Production(pnumber,prodname,syms,prodprec,func,file,line) + self.Productions.append(p) + self.Prodmap[map] = p + + # Add to the global productions list + try: + self.Prodnames[prodname].append(p) + except KeyError: + self.Prodnames[prodname] = [ p ] + return 0 + + # ----------------------------------------------------------------------------- + # set_start() + # + # Sets the starting symbol and creates the augmented grammar. Production + # rule 0 is S' -> start where start is the start symbol. + # ----------------------------------------------------------------------------- + + def set_start(self,start=None): + if not start: + start = self.Productions[1].name + if start not in self.Nonterminals: + raise GrammarError("start symbol %s undefined" % start) + self.Productions[0] = Production(0,"S'",[start]) + self.Nonterminals[start].append(0) + self.Start = start + + # ----------------------------------------------------------------------------- + # find_unreachable() + # + # Find all of the nonterminal symbols that can't be reached from the starting + # symbol. Returns a list of nonterminals that can't be reached. + # ----------------------------------------------------------------------------- + + def find_unreachable(self): + + # Mark all symbols that are reachable from a symbol s + def mark_reachable_from(s): + if reachable[s]: + # We've already reached symbol s. + return + reachable[s] = 1 + for p in self.Prodnames.get(s,[]): + for r in p.prod: + mark_reachable_from(r) + + reachable = { } + for s in list(self.Terminals) + list(self.Nonterminals): + reachable[s] = 0 + + mark_reachable_from( self.Productions[0].prod[0] ) + + return [s for s in list(self.Nonterminals) + if not reachable[s]] + + # ----------------------------------------------------------------------------- + # infinite_cycles() + # + # This function looks at the various parsing rules and tries to detect + # infinite recursion cycles (grammar rules where there is no possible way + # to derive a string of only terminals). + # ----------------------------------------------------------------------------- + + def infinite_cycles(self): + terminates = {} + + # Terminals: + for t in self.Terminals: + terminates[t] = 1 + + terminates['$end'] = 1 + + # Nonterminals: + + # Initialize to false: + for n in self.Nonterminals: + terminates[n] = 0 + + # Then propagate termination until no change: + while 1: + some_change = 0 + for (n,pl) in self.Prodnames.items(): + # Nonterminal n terminates iff any of its productions terminates. + for p in pl: + # Production p terminates iff all of its rhs symbols terminate. + for s in p.prod: + if not terminates[s]: + # The symbol s does not terminate, + # so production p does not terminate. + p_terminates = 0 + break + else: + # didn't break from the loop, + # so every symbol s terminates + # so production p terminates. + p_terminates = 1 + + if p_terminates: + # symbol n terminates! + if not terminates[n]: + terminates[n] = 1 + some_change = 1 + # Don't need to consider any more productions for this n. + break + + if not some_change: + break + + infinite = [] + for (s,term) in terminates.items(): + if not term: + if not s in self.Prodnames and not s in self.Terminals and s != 'error': + # s is used-but-not-defined, and we've already warned of that, + # so it would be overkill to say that it's also non-terminating. + pass + else: + infinite.append(s) + + return infinite + + + # ----------------------------------------------------------------------------- + # undefined_symbols() + # + # Find all symbols that were used the grammar, but not defined as tokens or + # grammar rules. Returns a list of tuples (sym, prod) where sym in the symbol + # and prod is the production where the symbol was used. + # ----------------------------------------------------------------------------- + def undefined_symbols(self): + result = [] + for p in self.Productions: + if not p: continue + + for s in p.prod: + if not s in self.Prodnames and not s in self.Terminals and s != 'error': + result.append((s,p)) + return result + + # ----------------------------------------------------------------------------- + # unused_terminals() + # + # Find all terminals that were defined, but not used by the grammar. Returns + # a list of all symbols. + # ----------------------------------------------------------------------------- + def unused_terminals(self): + unused_tok = [] + for s,v in self.Terminals.items(): + if s != 'error' and not v: + unused_tok.append(s) + + return unused_tok + + # ------------------------------------------------------------------------------ + # unused_rules() + # + # Find all grammar rules that were defined, but not used (maybe not reachable) + # Returns a list of productions. + # ------------------------------------------------------------------------------ + + def unused_rules(self): + unused_prod = [] + for s,v in self.Nonterminals.items(): + if not v: + p = self.Prodnames[s][0] + unused_prod.append(p) + return unused_prod + + # ----------------------------------------------------------------------------- + # unused_precedence() + # + # Returns a list of tuples (term,precedence) corresponding to precedence + # rules that were never used by the grammar. term is the name of the terminal + # on which precedence was applied and precedence is a string such as 'left' or + # 'right' corresponding to the type of precedence. + # ----------------------------------------------------------------------------- + + def unused_precedence(self): + unused = [] + for termname in self.Precedence: + if not (termname in self.Terminals or termname in self.UsedPrecedence): + unused.append((termname,self.Precedence[termname][0])) + + return unused + + # ------------------------------------------------------------------------- + # _first() + # + # Compute the value of FIRST1(beta) where beta is a tuple of symbols. + # + # During execution of compute_first1, the result may be incomplete. + # Afterward (e.g., when called from compute_follow()), it will be complete. + # ------------------------------------------------------------------------- + def _first(self,beta): + + # We are computing First(x1,x2,x3,...,xn) + result = [ ] + for x in beta: + x_produces_empty = 0 + + # Add all the non- symbols of First[x] to the result. + for f in self.First[x]: + if f == '': + x_produces_empty = 1 + else: + if f not in result: result.append(f) + + if x_produces_empty: + # We have to consider the next x in beta, + # i.e. stay in the loop. + pass + else: + # We don't have to consider any further symbols in beta. + break + else: + # There was no 'break' from the loop, + # so x_produces_empty was true for all x in beta, + # so beta produces empty as well. + result.append('') + + return result + + # ------------------------------------------------------------------------- + # compute_first() + # + # Compute the value of FIRST1(X) for all symbols + # ------------------------------------------------------------------------- + def compute_first(self): + if self.First: + return self.First + + # Terminals: + for t in self.Terminals: + self.First[t] = [t] + + self.First['$end'] = ['$end'] + + # Nonterminals: + + # Initialize to the empty set: + for n in self.Nonterminals: + self.First[n] = [] + + # Then propagate symbols until no change: + while 1: + some_change = 0 + for n in self.Nonterminals: + for p in self.Prodnames[n]: + for f in self._first(p.prod): + if f not in self.First[n]: + self.First[n].append( f ) + some_change = 1 + if not some_change: + break + + return self.First + + # --------------------------------------------------------------------- + # compute_follow() + # + # Computes all of the follow sets for every non-terminal symbol. The + # follow set is the set of all symbols that might follow a given + # non-terminal. See the Dragon book, 2nd Ed. p. 189. + # --------------------------------------------------------------------- + def compute_follow(self,start=None): + # If already computed, return the result + if self.Follow: + return self.Follow + + # If first sets not computed yet, do that first. + if not self.First: + self.compute_first() + + # Add '$end' to the follow list of the start symbol + for k in self.Nonterminals: + self.Follow[k] = [ ] + + if not start: + start = self.Productions[1].name + + self.Follow[start] = [ '$end' ] + + while 1: + didadd = 0 + for p in self.Productions[1:]: + # Here is the production set + for i in range(len(p.prod)): + B = p.prod[i] + if B in self.Nonterminals: + # Okay. We got a non-terminal in a production + fst = self._first(p.prod[i+1:]) + hasempty = 0 + for f in fst: + if f != '' and f not in self.Follow[B]: + self.Follow[B].append(f) + didadd = 1 + if f == '': + hasempty = 1 + if hasempty or i == (len(p.prod)-1): + # Add elements of follow(a) to follow(b) + for f in self.Follow[p.name]: + if f not in self.Follow[B]: + self.Follow[B].append(f) + didadd = 1 + if not didadd: break + return self.Follow + + + # ----------------------------------------------------------------------------- + # build_lritems() + # + # This function walks the list of productions and builds a complete set of the + # LR items. The LR items are stored in two ways: First, they are uniquely + # numbered and placed in the list _lritems. Second, a linked list of LR items + # is built for each production. For example: + # + # E -> E PLUS E + # + # Creates the list + # + # [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ] + # ----------------------------------------------------------------------------- + + def build_lritems(self): + for p in self.Productions: + lastlri = p + i = 0 + lr_items = [] + while 1: + if i > len(p): + lri = None + else: + lri = LRItem(p,i) + # Precompute the list of productions immediately following + try: + lri.lr_after = self.Prodnames[lri.prod[i+1]] + except (IndexError,KeyError): + lri.lr_after = [] + try: + lri.lr_before = lri.prod[i-1] + except IndexError: + lri.lr_before = None + + lastlri.lr_next = lri + if not lri: break + lr_items.append(lri) + lastlri = lri + i += 1 + p.lr_items = lr_items + +# ----------------------------------------------------------------------------- +# == Class LRTable == +# +# This basic class represents a basic table of LR parsing information. +# Methods for generating the tables are not defined here. They are defined +# in the derived class LRGeneratedTable. +# ----------------------------------------------------------------------------- + +class VersionError(YaccError): pass + +class LRTable(object): + def __init__(self): + self.lr_action = None + self.lr_goto = None + self.lr_productions = None + self.lr_method = None + + def read_table(self,module): + if isinstance(module,types.ModuleType): + parsetab = module + else: + if sys.version_info[0] < 3: + exec("import %s as parsetab" % module) + else: + env = { } + exec("import %s as parsetab" % module, env, env) + parsetab = env['parsetab'] + + if parsetab._tabversion != __tabversion__: + raise VersionError("yacc table file version is out of date") + + self.lr_action = parsetab._lr_action + self.lr_goto = parsetab._lr_goto + + self.lr_productions = [] + for p in parsetab._lr_productions: + self.lr_productions.append(MiniProduction(*p)) + + self.lr_method = parsetab._lr_method + return parsetab._lr_signature + + def read_pickle(self,filename): + try: + import cPickle as pickle + except ImportError: + import pickle + + in_f = open(filename,"rb") + + tabversion = pickle.load(in_f) + if tabversion != __tabversion__: + raise VersionError("yacc table file version is out of date") + self.lr_method = pickle.load(in_f) + signature = pickle.load(in_f) + self.lr_action = pickle.load(in_f) + self.lr_goto = pickle.load(in_f) + productions = pickle.load(in_f) + + self.lr_productions = [] + for p in productions: + self.lr_productions.append(MiniProduction(*p)) + + in_f.close() + return signature + + # Bind all production function names to callable objects in pdict + def bind_callables(self,pdict): + for p in self.lr_productions: + p.bind(pdict) + +# ----------------------------------------------------------------------------- +# === LR Generator === +# +# The following classes and functions are used to generate LR parsing tables on +# a grammar. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# digraph() +# traverse() +# +# The following two functions are used to compute set valued functions +# of the form: +# +# F(x) = F'(x) U U{F(y) | x R y} +# +# This is used to compute the values of Read() sets as well as FOLLOW sets +# in LALR(1) generation. +# +# Inputs: X - An input set +# R - A relation +# FP - Set-valued function +# ------------------------------------------------------------------------------ + +def digraph(X,R,FP): + N = { } + for x in X: + N[x] = 0 + stack = [] + F = { } + for x in X: + if N[x] == 0: traverse(x,N,stack,F,X,R,FP) + return F + +def traverse(x,N,stack,F,X,R,FP): + stack.append(x) + d = len(stack) + N[x] = d + F[x] = FP(x) # F(X) <- F'(x) + + rel = R(x) # Get y's related to x + for y in rel: + if N[y] == 0: + traverse(y,N,stack,F,X,R,FP) + N[x] = min(N[x],N[y]) + for a in F.get(y,[]): + if a not in F[x]: F[x].append(a) + if N[x] == d: + N[stack[-1]] = MAXINT + F[stack[-1]] = F[x] + element = stack.pop() + while element != x: + N[stack[-1]] = MAXINT + F[stack[-1]] = F[x] + element = stack.pop() + +class LALRError(YaccError): pass + +# ----------------------------------------------------------------------------- +# == LRGeneratedTable == +# +# This class implements the LR table generation algorithm. There are no +# public methods except for write() +# ----------------------------------------------------------------------------- + +class LRGeneratedTable(LRTable): + def __init__(self,grammar,method='LALR',log=None): + if method not in ['SLR','LALR']: + raise LALRError("Unsupported method %s" % method) + + self.grammar = grammar + self.lr_method = method + + # Set up the logger + if not log: + log = NullLogger() + self.log = log + + # Internal attributes + self.lr_action = {} # Action table + self.lr_goto = {} # Goto table + self.lr_productions = grammar.Productions # Copy of grammar Production array + self.lr_goto_cache = {} # Cache of computed gotos + self.lr0_cidhash = {} # Cache of closures + + self._add_count = 0 # Internal counter used to detect cycles + + # Diagonistic information filled in by the table generator + self.sr_conflict = 0 + self.rr_conflict = 0 + self.conflicts = [] # List of conflicts + + self.sr_conflicts = [] + self.rr_conflicts = [] + + # Build the tables + self.grammar.build_lritems() + self.grammar.compute_first() + self.grammar.compute_follow() + self.lr_parse_table() + + # Compute the LR(0) closure operation on I, where I is a set of LR(0) items. + + def lr0_closure(self,I): + self._add_count += 1 + + # Add everything in I to J + J = I[:] + didadd = 1 + while didadd: + didadd = 0 + for j in J: + for x in j.lr_after: + if getattr(x,"lr0_added",0) == self._add_count: continue + # Add B --> .G to J + J.append(x.lr_next) + x.lr0_added = self._add_count + didadd = 1 + + return J + + # Compute the LR(0) goto function goto(I,X) where I is a set + # of LR(0) items and X is a grammar symbol. This function is written + # in a way that guarantees uniqueness of the generated goto sets + # (i.e. the same goto set will never be returned as two different Python + # objects). With uniqueness, we can later do fast set comparisons using + # id(obj) instead of element-wise comparison. + + def lr0_goto(self,I,x): + # First we look for a previously cached entry + g = self.lr_goto_cache.get((id(I),x),None) + if g: return g + + # Now we generate the goto set in a way that guarantees uniqueness + # of the result + + s = self.lr_goto_cache.get(x,None) + if not s: + s = { } + self.lr_goto_cache[x] = s + + gs = [ ] + for p in I: + n = p.lr_next + if n and n.lr_before == x: + s1 = s.get(id(n),None) + if not s1: + s1 = { } + s[id(n)] = s1 + gs.append(n) + s = s1 + g = s.get('$end',None) + if not g: + if gs: + g = self.lr0_closure(gs) + s['$end'] = g + else: + s['$end'] = gs + self.lr_goto_cache[(id(I),x)] = g + return g + + # Compute the LR(0) sets of item function + def lr0_items(self): + + C = [ self.lr0_closure([self.grammar.Productions[0].lr_next]) ] + i = 0 + for I in C: + self.lr0_cidhash[id(I)] = i + i += 1 + + # Loop over the items in C and each grammar symbols + i = 0 + while i < len(C): + I = C[i] + i += 1 + + # Collect all of the symbols that could possibly be in the goto(I,X) sets + asyms = { } + for ii in I: + for s in ii.usyms: + asyms[s] = None + + for x in asyms: + g = self.lr0_goto(I,x) + if not g: continue + if id(g) in self.lr0_cidhash: continue + self.lr0_cidhash[id(g)] = len(C) + C.append(g) + + return C + + # ----------------------------------------------------------------------------- + # ==== LALR(1) Parsing ==== + # + # LALR(1) parsing is almost exactly the same as SLR except that instead of + # relying upon Follow() sets when performing reductions, a more selective + # lookahead set that incorporates the state of the LR(0) machine is utilized. + # Thus, we mainly just have to focus on calculating the lookahead sets. + # + # The method used here is due to DeRemer and Pennelo (1982). + # + # DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1) + # Lookahead Sets", ACM Transactions on Programming Languages and Systems, + # Vol. 4, No. 4, Oct. 1982, pp. 615-649 + # + # Further details can also be found in: + # + # J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing", + # McGraw-Hill Book Company, (1985). + # + # ----------------------------------------------------------------------------- + + # ----------------------------------------------------------------------------- + # compute_nullable_nonterminals() + # + # Creates a dictionary containing all of the non-terminals that might produce + # an empty production. + # ----------------------------------------------------------------------------- + + def compute_nullable_nonterminals(self): + nullable = {} + num_nullable = 0 + while 1: + for p in self.grammar.Productions[1:]: + if p.len == 0: + nullable[p.name] = 1 + continue + for t in p.prod: + if not t in nullable: break + else: + nullable[p.name] = 1 + if len(nullable) == num_nullable: break + num_nullable = len(nullable) + return nullable + + # ----------------------------------------------------------------------------- + # find_nonterminal_trans(C) + # + # Given a set of LR(0) items, this functions finds all of the non-terminal + # transitions. These are transitions in which a dot appears immediately before + # a non-terminal. Returns a list of tuples of the form (state,N) where state + # is the state number and N is the nonterminal symbol. + # + # The input C is the set of LR(0) items. + # ----------------------------------------------------------------------------- + + def find_nonterminal_transitions(self,C): + trans = [] + for state in range(len(C)): + for p in C[state]: + if p.lr_index < p.len - 1: + t = (state,p.prod[p.lr_index+1]) + if t[1] in self.grammar.Nonterminals: + if t not in trans: trans.append(t) + state = state + 1 + return trans + + # ----------------------------------------------------------------------------- + # dr_relation() + # + # Computes the DR(p,A) relationships for non-terminal transitions. The input + # is a tuple (state,N) where state is a number and N is a nonterminal symbol. + # + # Returns a list of terminals. + # ----------------------------------------------------------------------------- + + def dr_relation(self,C,trans,nullable): + dr_set = { } + state,N = trans + terms = [] + + g = self.lr0_goto(C[state],N) + for p in g: + if p.lr_index < p.len - 1: + a = p.prod[p.lr_index+1] + if a in self.grammar.Terminals: + if a not in terms: terms.append(a) + + # This extra bit is to handle the start state + if state == 0 and N == self.grammar.Productions[0].prod[0]: + terms.append('$end') + + return terms + + # ----------------------------------------------------------------------------- + # reads_relation() + # + # Computes the READS() relation (p,A) READS (t,C). + # ----------------------------------------------------------------------------- + + def reads_relation(self,C, trans, empty): + # Look for empty transitions + rel = [] + state, N = trans + + g = self.lr0_goto(C[state],N) + j = self.lr0_cidhash.get(id(g),-1) + for p in g: + if p.lr_index < p.len - 1: + a = p.prod[p.lr_index + 1] + if a in empty: + rel.append((j,a)) + + return rel + + # ----------------------------------------------------------------------------- + # compute_lookback_includes() + # + # Determines the lookback and includes relations + # + # LOOKBACK: + # + # This relation is determined by running the LR(0) state machine forward. + # For example, starting with a production "N : . A B C", we run it forward + # to obtain "N : A B C ." We then build a relationship between this final + # state and the starting state. These relationships are stored in a dictionary + # lookdict. + # + # INCLUDES: + # + # Computes the INCLUDE() relation (p,A) INCLUDES (p',B). + # + # This relation is used to determine non-terminal transitions that occur + # inside of other non-terminal transition states. (p,A) INCLUDES (p', B) + # if the following holds: + # + # B -> LAT, where T -> epsilon and p' -L-> p + # + # L is essentially a prefix (which may be empty), T is a suffix that must be + # able to derive an empty string. State p' must lead to state p with the string L. + # + # ----------------------------------------------------------------------------- + + def compute_lookback_includes(self,C,trans,nullable): + + lookdict = {} # Dictionary of lookback relations + includedict = {} # Dictionary of include relations + + # Make a dictionary of non-terminal transitions + dtrans = {} + for t in trans: + dtrans[t] = 1 + + # Loop over all transitions and compute lookbacks and includes + for state,N in trans: + lookb = [] + includes = [] + for p in C[state]: + if p.name != N: continue + + # Okay, we have a name match. We now follow the production all the way + # through the state machine until we get the . on the right hand side + + lr_index = p.lr_index + j = state + while lr_index < p.len - 1: + lr_index = lr_index + 1 + t = p.prod[lr_index] + + # Check to see if this symbol and state are a non-terminal transition + if (j,t) in dtrans: + # Yes. Okay, there is some chance that this is an includes relation + # the only way to know for certain is whether the rest of the + # production derives empty + + li = lr_index + 1 + while li < p.len: + if p.prod[li] in self.grammar.Terminals: break # No forget it + if not p.prod[li] in nullable: break + li = li + 1 + else: + # Appears to be a relation between (j,t) and (state,N) + includes.append((j,t)) + + g = self.lr0_goto(C[j],t) # Go to next set + j = self.lr0_cidhash.get(id(g),-1) # Go to next state + + # When we get here, j is the final state, now we have to locate the production + for r in C[j]: + if r.name != p.name: continue + if r.len != p.len: continue + i = 0 + # This look is comparing a production ". A B C" with "A B C ." + while i < r.lr_index: + if r.prod[i] != p.prod[i+1]: break + i = i + 1 + else: + lookb.append((j,r)) + for i in includes: + if not i in includedict: includedict[i] = [] + includedict[i].append((state,N)) + lookdict[(state,N)] = lookb + + return lookdict,includedict + + # ----------------------------------------------------------------------------- + # compute_read_sets() + # + # Given a set of LR(0) items, this function computes the read sets. + # + # Inputs: C = Set of LR(0) items + # ntrans = Set of nonterminal transitions + # nullable = Set of empty transitions + # + # Returns a set containing the read sets + # ----------------------------------------------------------------------------- + + def compute_read_sets(self,C, ntrans, nullable): + FP = lambda x: self.dr_relation(C,x,nullable) + R = lambda x: self.reads_relation(C,x,nullable) + F = digraph(ntrans,R,FP) + return F + + # ----------------------------------------------------------------------------- + # compute_follow_sets() + # + # Given a set of LR(0) items, a set of non-terminal transitions, a readset, + # and an include set, this function computes the follow sets + # + # Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)} + # + # Inputs: + # ntrans = Set of nonterminal transitions + # readsets = Readset (previously computed) + # inclsets = Include sets (previously computed) + # + # Returns a set containing the follow sets + # ----------------------------------------------------------------------------- + + def compute_follow_sets(self,ntrans,readsets,inclsets): + FP = lambda x: readsets[x] + R = lambda x: inclsets.get(x,[]) + F = digraph(ntrans,R,FP) + return F + + # ----------------------------------------------------------------------------- + # add_lookaheads() + # + # Attaches the lookahead symbols to grammar rules. + # + # Inputs: lookbacks - Set of lookback relations + # followset - Computed follow set + # + # This function directly attaches the lookaheads to productions contained + # in the lookbacks set + # ----------------------------------------------------------------------------- + + def add_lookaheads(self,lookbacks,followset): + for trans,lb in lookbacks.items(): + # Loop over productions in lookback + for state,p in lb: + if not state in p.lookaheads: + p.lookaheads[state] = [] + f = followset.get(trans,[]) + for a in f: + if a not in p.lookaheads[state]: p.lookaheads[state].append(a) + + # ----------------------------------------------------------------------------- + # add_lalr_lookaheads() + # + # This function does all of the work of adding lookahead information for use + # with LALR parsing + # ----------------------------------------------------------------------------- + + def add_lalr_lookaheads(self,C): + # Determine all of the nullable nonterminals + nullable = self.compute_nullable_nonterminals() + + # Find all non-terminal transitions + trans = self.find_nonterminal_transitions(C) + + # Compute read sets + readsets = self.compute_read_sets(C,trans,nullable) + + # Compute lookback/includes relations + lookd, included = self.compute_lookback_includes(C,trans,nullable) + + # Compute LALR FOLLOW sets + followsets = self.compute_follow_sets(trans,readsets,included) + + # Add all of the lookaheads + self.add_lookaheads(lookd,followsets) + + # ----------------------------------------------------------------------------- + # lr_parse_table() + # + # This function constructs the parse tables for SLR or LALR + # ----------------------------------------------------------------------------- + def lr_parse_table(self): + Productions = self.grammar.Productions + Precedence = self.grammar.Precedence + goto = self.lr_goto # Goto array + action = self.lr_action # Action array + log = self.log # Logger for output + + actionp = { } # Action production array (temporary) + + log.info("Parsing method: %s", self.lr_method) + + # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items + # This determines the number of states + + C = self.lr0_items() + + if self.lr_method == 'LALR': + self.add_lalr_lookaheads(C) + + # Build the parser table, state by state + st = 0 + for I in C: + # Loop over each production in I + actlist = [ ] # List of actions + st_action = { } + st_actionp = { } + st_goto = { } + log.info("") + log.info("state %d", st) + log.info("") + for p in I: + log.info(" (%d) %s", p.number, str(p)) + log.info("") + + for p in I: + if p.len == p.lr_index + 1: + if p.name == "S'": + # Start symbol. Accept! + st_action["$end"] = 0 + st_actionp["$end"] = p + else: + # We are at the end of a production. Reduce! + if self.lr_method == 'LALR': + laheads = p.lookaheads[st] + else: + laheads = self.grammar.Follow[p.name] + for a in laheads: + actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p))) + r = st_action.get(a,None) + if r is not None: + # Whoa. Have a shift/reduce or reduce/reduce conflict + if r > 0: + # Need to decide on shift or reduce here + # By default we favor shifting. Need to add + # some precedence rules here. + sprec,slevel = Productions[st_actionp[a].number].prec + rprec,rlevel = Precedence.get(a,('right',0)) + if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')): + # We really need to reduce here. + st_action[a] = -p.number + st_actionp[a] = p + if not slevel and not rlevel: + log.info(" ! shift/reduce conflict for %s resolved as reduce",a) + self.sr_conflicts.append((st,a,'reduce')) + Productions[p.number].reduced += 1 + elif (slevel == rlevel) and (rprec == 'nonassoc'): + st_action[a] = None + else: + # Hmmm. Guess we'll keep the shift + if not rlevel: + log.info(" ! shift/reduce conflict for %s resolved as shift",a) + self.sr_conflicts.append((st,a,'shift')) + elif r < 0: + # Reduce/reduce conflict. In this case, we favor the rule + # that was defined first in the grammar file + oldp = Productions[-r] + pp = Productions[p.number] + if oldp.line > pp.line: + st_action[a] = -p.number + st_actionp[a] = p + chosenp,rejectp = pp,oldp + Productions[p.number].reduced += 1 + Productions[oldp.number].reduced -= 1 + else: + chosenp,rejectp = oldp,pp + self.rr_conflicts.append((st,chosenp,rejectp)) + log.info(" ! reduce/reduce conflict for %s resolved using rule %d (%s)", a,st_actionp[a].number, st_actionp[a]) + else: + raise LALRError("Unknown conflict in state %d" % st) + else: + st_action[a] = -p.number + st_actionp[a] = p + Productions[p.number].reduced += 1 + else: + i = p.lr_index + a = p.prod[i+1] # Get symbol right after the "." + if a in self.grammar.Terminals: + g = self.lr0_goto(I,a) + j = self.lr0_cidhash.get(id(g),-1) + if j >= 0: + # We are in a shift state + actlist.append((a,p,"shift and go to state %d" % j)) + r = st_action.get(a,None) + if r is not None: + # Whoa have a shift/reduce or shift/shift conflict + if r > 0: + if r != j: + raise LALRError("Shift/shift conflict in state %d" % st) + elif r < 0: + # Do a precedence check. + # - if precedence of reduce rule is higher, we reduce. + # - if precedence of reduce is same and left assoc, we reduce. + # - otherwise we shift + rprec,rlevel = Productions[st_actionp[a].number].prec + sprec,slevel = Precedence.get(a,('right',0)) + if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')): + # We decide to shift here... highest precedence to shift + Productions[st_actionp[a].number].reduced -= 1 + st_action[a] = j + st_actionp[a] = p + if not rlevel: + log.info(" ! shift/reduce conflict for %s resolved as shift",a) + self.sr_conflicts.append((st,a,'shift')) + elif (slevel == rlevel) and (rprec == 'nonassoc'): + st_action[a] = None + else: + # Hmmm. Guess we'll keep the reduce + if not slevel and not rlevel: + log.info(" ! shift/reduce conflict for %s resolved as reduce",a) + self.sr_conflicts.append((st,a,'reduce')) + + else: + raise LALRError("Unknown conflict in state %d" % st) + else: + st_action[a] = j + st_actionp[a] = p + + # Print the actions associated with each terminal + _actprint = { } + for a,p,m in actlist: + if a in st_action: + if p is st_actionp[a]: + log.info(" %-15s %s",a,m) + _actprint[(a,m)] = 1 + log.info("") + # Print the actions that were not used. (debugging) + not_used = 0 + for a,p,m in actlist: + if a in st_action: + if p is not st_actionp[a]: + if not (a,m) in _actprint: + log.debug(" ! %-15s [ %s ]",a,m) + not_used = 1 + _actprint[(a,m)] = 1 + if not_used: + log.debug("") + + # Construct the goto table for this state + + nkeys = { } + for ii in I: + for s in ii.usyms: + if s in self.grammar.Nonterminals: + nkeys[s] = None + for n in nkeys: + g = self.lr0_goto(I,n) + j = self.lr0_cidhash.get(id(g),-1) + if j >= 0: + st_goto[n] = j + log.info(" %-30s shift and go to state %d",n,j) + + action[st] = st_action + actionp[st] = st_actionp + goto[st] = st_goto + st += 1 + + + # ----------------------------------------------------------------------------- + # write() + # + # This function writes the LR parsing tables to a file + # ----------------------------------------------------------------------------- + + def write_table(self,modulename,outputdir='',signature=""): + basemodulename = modulename.split(".")[-1] + filename = os.path.join(outputdir,basemodulename) + ".py" + try: + f = open(filename,"w") + + f.write(""" +# %s +# This file is automatically generated. Do not edit. +_tabversion = %r + +_lr_method = %r + +_lr_signature = %r + """ % (filename, __tabversion__, self.lr_method, signature)) + + # Change smaller to 0 to go back to original tables + smaller = 1 + + # Factor out names to try and make smaller + if smaller: + items = { } + + for s,nd in self.lr_action.items(): + for name,v in nd.items(): + i = items.get(name) + if not i: + i = ([],[]) + items[name] = i + i[0].append(s) + i[1].append(v) + + f.write("\n_lr_action_items = {") + for k,v in items.items(): + f.write("%r:([" % k) + for i in v[0]: + f.write("%r," % i) + f.write("],[") + for i in v[1]: + f.write("%r," % i) + + f.write("]),") + f.write("}\n") + + f.write(""" +_lr_action = { } +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = { } + _lr_action[_x][_k] = _y +del _lr_action_items +""") + + else: + f.write("\n_lr_action = { "); + for k,v in self.lr_action.items(): + f.write("(%r,%r):%r," % (k[0],k[1],v)) + f.write("}\n"); + + if smaller: + # Factor out names to try and make smaller + items = { } + + for s,nd in self.lr_goto.items(): + for name,v in nd.items(): + i = items.get(name) + if not i: + i = ([],[]) + items[name] = i + i[0].append(s) + i[1].append(v) + + f.write("\n_lr_goto_items = {") + for k,v in items.items(): + f.write("%r:([" % k) + for i in v[0]: + f.write("%r," % i) + f.write("],[") + for i in v[1]: + f.write("%r," % i) + + f.write("]),") + f.write("}\n") + + f.write(""" +_lr_goto = { } +for _k, _v in _lr_goto_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_goto: _lr_goto[_x] = { } + _lr_goto[_x][_k] = _y +del _lr_goto_items +""") + else: + f.write("\n_lr_goto = { "); + for k,v in self.lr_goto.items(): + f.write("(%r,%r):%r," % (k[0],k[1],v)) + f.write("}\n"); + + # Write production table + f.write("_lr_productions = [\n") + for p in self.lr_productions: + if p.func: + f.write(" (%r,%r,%d,%r,%r,%d),\n" % (p.str,p.name, p.len, p.func,p.file,p.line)) + else: + f.write(" (%r,%r,%d,None,None,None),\n" % (str(p),p.name, p.len)) + f.write("]\n") + f.close() + + except IOError: + e = sys.exc_info()[1] + sys.stderr.write("Unable to create '%s'\n" % filename) + sys.stderr.write(str(e)+"\n") + return + + + # ----------------------------------------------------------------------------- + # pickle_table() + # + # This function pickles the LR parsing tables to a supplied file object + # ----------------------------------------------------------------------------- + + def pickle_table(self,filename,signature=""): + try: + import cPickle as pickle + except ImportError: + import pickle + outf = open(filename,"wb") + pickle.dump(__tabversion__,outf,pickle_protocol) + pickle.dump(self.lr_method,outf,pickle_protocol) + pickle.dump(signature,outf,pickle_protocol) + pickle.dump(self.lr_action,outf,pickle_protocol) + pickle.dump(self.lr_goto,outf,pickle_protocol) + + outp = [] + for p in self.lr_productions: + if p.func: + outp.append((p.str,p.name, p.len, p.func,p.file,p.line)) + else: + outp.append((str(p),p.name,p.len,None,None,None)) + pickle.dump(outp,outf,pickle_protocol) + outf.close() + +# ----------------------------------------------------------------------------- +# === INTROSPECTION === +# +# The following functions and classes are used to implement the PLY +# introspection features followed by the yacc() function itself. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# get_caller_module_dict() +# +# This function returns a dictionary containing all of the symbols defined within +# a caller further down the call stack. This is used to get the environment +# associated with the yacc() call if none was provided. +# ----------------------------------------------------------------------------- + +def get_caller_module_dict(levels): + try: + raise RuntimeError + except RuntimeError: + e,b,t = sys.exc_info() + f = t.tb_frame + while levels > 0: + f = f.f_back + levels -= 1 + ldict = f.f_globals.copy() + if f.f_globals != f.f_locals: + ldict.update(f.f_locals) + + return ldict + +# ----------------------------------------------------------------------------- +# parse_grammar() +# +# This takes a raw grammar rule string and parses it into production data +# ----------------------------------------------------------------------------- +def parse_grammar(doc,file,line): + grammar = [] + # Split the doc string into lines + pstrings = doc.splitlines() + lastp = None + dline = line + for ps in pstrings: + dline += 1 + p = ps.split() + if not p: continue + try: + if p[0] == '|': + # This is a continuation of a previous rule + if not lastp: + raise SyntaxError("%s:%d: Misplaced '|'" % (file,dline)) + prodname = lastp + syms = p[1:] + else: + prodname = p[0] + lastp = prodname + syms = p[2:] + assign = p[1] + if assign != ':' and assign != '::=': + raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file,dline)) + + grammar.append((file,dline,prodname,syms)) + except SyntaxError: + raise + except Exception: + raise SyntaxError("%s:%d: Syntax error in rule '%s'" % (file,dline,ps.strip())) + + return grammar + +# ----------------------------------------------------------------------------- +# ParserReflect() +# +# This class represents information extracted for building a parser including +# start symbol, error function, tokens, precedence list, action functions, +# etc. +# ----------------------------------------------------------------------------- +class ParserReflect(object): + def __init__(self,pdict,log=None): + self.pdict = pdict + self.start = None + self.error_func = None + self.tokens = None + self.files = {} + self.grammar = [] + self.error = 0 + + if log is None: + self.log = PlyLogger(sys.stderr) + else: + self.log = log + + # Get all of the basic information + def get_all(self): + self.get_start() + self.get_error_func() + self.get_tokens() + self.get_precedence() + self.get_pfunctions() + + # Validate all of the information + def validate_all(self): + self.validate_start() + self.validate_error_func() + self.validate_tokens() + self.validate_precedence() + self.validate_pfunctions() + self.validate_files() + return self.error + + # Compute a signature over the grammar + def signature(self): + try: + from hashlib import md5 + except ImportError: + from md5 import md5 + try: + sig = md5() + if self.start: + sig.update(self.start.encode('latin-1')) + if self.prec: + sig.update("".join(["".join(p) for p in self.prec]).encode('latin-1')) + if self.tokens: + sig.update(" ".join(self.tokens).encode('latin-1')) + for f in self.pfuncs: + if f[3]: + sig.update(f[3].encode('latin-1')) + except (TypeError,ValueError): + pass + return sig.digest() + + # ----------------------------------------------------------------------------- + # validate_file() + # + # This method checks to see if there are duplicated p_rulename() functions + # in the parser module file. Without this function, it is really easy for + # users to make mistakes by cutting and pasting code fragments (and it's a real + # bugger to try and figure out why the resulting parser doesn't work). Therefore, + # we just do a little regular expression pattern matching of def statements + # to try and detect duplicates. + # ----------------------------------------------------------------------------- + + def validate_files(self): + # Match def p_funcname( + fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(') + + for filename in self.files.keys(): + base,ext = os.path.splitext(filename) + if ext != '.py': return 1 # No idea. Assume it's okay. + + try: + f = open(filename) + lines = f.readlines() + f.close() + except IOError: + continue + + counthash = { } + for linen,l in enumerate(lines): + linen += 1 + m = fre.match(l) + if m: + name = m.group(1) + prev = counthash.get(name) + if not prev: + counthash[name] = linen + else: + self.log.warning("%s:%d: Function %s redefined. Previously defined on line %d", filename,linen,name,prev) + + # Get the start symbol + def get_start(self): + self.start = self.pdict.get('start') + + # Validate the start symbol + def validate_start(self): + if self.start is not None: + if not isinstance(self.start,str): + self.log.error("'start' must be a string") + + # Look for error handler + def get_error_func(self): + self.error_func = self.pdict.get('p_error') + + # Validate the error function + def validate_error_func(self): + if self.error_func: + if isinstance(self.error_func,types.FunctionType): + ismethod = 0 + elif isinstance(self.error_func, types.MethodType): + ismethod = 1 + else: + self.log.error("'p_error' defined, but is not a function or method") + self.error = 1 + return + + eline = func_code(self.error_func).co_firstlineno + efile = func_code(self.error_func).co_filename + self.files[efile] = 1 + + if (func_code(self.error_func).co_argcount != 1+ismethod): + self.log.error("%s:%d: p_error() requires 1 argument",efile,eline) + self.error = 1 + + # Get the tokens map + def get_tokens(self): + tokens = self.pdict.get("tokens",None) + if not tokens: + self.log.error("No token list is defined") + self.error = 1 + return + + if not isinstance(tokens,(list, tuple)): + self.log.error("tokens must be a list or tuple") + self.error = 1 + return + + if not tokens: + self.log.error("tokens is empty") + self.error = 1 + return + + self.tokens = tokens + + # Validate the tokens + def validate_tokens(self): + # Validate the tokens. + if 'error' in self.tokens: + self.log.error("Illegal token name 'error'. Is a reserved word") + self.error = 1 + return + + terminals = {} + for n in self.tokens: + if n in terminals: + self.log.warning("Token '%s' multiply defined", n) + terminals[n] = 1 + + # Get the precedence map (if any) + def get_precedence(self): + self.prec = self.pdict.get("precedence",None) + + # Validate and parse the precedence map + def validate_precedence(self): + preclist = [] + if self.prec: + if not isinstance(self.prec,(list,tuple)): + self.log.error("precedence must be a list or tuple") + self.error = 1 + return + for level,p in enumerate(self.prec): + if not isinstance(p,(list,tuple)): + self.log.error("Bad precedence table") + self.error = 1 + return + + if len(p) < 2: + self.log.error("Malformed precedence entry %s. Must be (assoc, term, ..., term)",p) + self.error = 1 + return + assoc = p[0] + if not isinstance(assoc,str): + self.log.error("precedence associativity must be a string") + self.error = 1 + return + for term in p[1:]: + if not isinstance(term,str): + self.log.error("precedence items must be strings") + self.error = 1 + return + preclist.append((term,assoc,level+1)) + self.preclist = preclist + + # Get all p_functions from the grammar + def get_pfunctions(self): + p_functions = [] + for name, item in self.pdict.items(): + if name[:2] != 'p_': continue + if name == 'p_error': continue + if isinstance(item,(types.FunctionType,types.MethodType)): + line = func_code(item).co_firstlineno + file = func_code(item).co_filename + p_functions.append((line,file,name,item.__doc__)) + + # Sort all of the actions by line number + p_functions.sort() + self.pfuncs = p_functions + + + # Validate all of the p_functions + def validate_pfunctions(self): + grammar = [] + # Check for non-empty symbols + if len(self.pfuncs) == 0: + self.log.error("no rules of the form p_rulename are defined") + self.error = 1 + return + + for line, file, name, doc in self.pfuncs: + func = self.pdict[name] + if isinstance(func, types.MethodType): + reqargs = 2 + else: + reqargs = 1 + if func_code(func).co_argcount > reqargs: + self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,func.__name__) + self.error = 1 + elif func_code(func).co_argcount < reqargs: + self.log.error("%s:%d: Rule '%s' requires an argument",file,line,func.__name__) + self.error = 1 + elif not func.__doc__: + self.log.warning("%s:%d: No documentation string specified in function '%s' (ignored)",file,line,func.__name__) + else: + try: + parsed_g = parse_grammar(doc,file,line) + for g in parsed_g: + grammar.append((name, g)) + except SyntaxError: + e = sys.exc_info()[1] + self.log.error(str(e)) + self.error = 1 + + # Looks like a valid grammar rule + # Mark the file in which defined. + self.files[file] = 1 + + # Secondary validation step that looks for p_ definitions that are not functions + # or functions that look like they might be grammar rules. + + for n,v in self.pdict.items(): + if n[0:2] == 'p_' and isinstance(v, (types.FunctionType, types.MethodType)): continue + if n[0:2] == 't_': continue + if n[0:2] == 'p_' and n != 'p_error': + self.log.warning("'%s' not defined as a function", n) + if ((isinstance(v,types.FunctionType) and func_code(v).co_argcount == 1) or + (isinstance(v,types.MethodType) and func_code(v).co_argcount == 2)): + try: + doc = v.__doc__.split(" ") + if doc[1] == ':': + self.log.warning("%s:%d: Possible grammar rule '%s' defined without p_ prefix", + func_code(v).co_filename, func_code(v).co_firstlineno,n) + except Exception: + pass + + self.grammar = grammar + +# ----------------------------------------------------------------------------- +# yacc(module) +# +# Build a parser +# ----------------------------------------------------------------------------- + +def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, + check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='', + debuglog=None, errorlog = None, picklefile=None): + + global parse # Reference to the parsing method of the last built parser + + # If pickling is enabled, table files are not created + + if picklefile: + write_tables = 0 + + if errorlog is None: + errorlog = PlyLogger(sys.stderr) + + # Get the module dictionary used for the parser + if module: + _items = [(k,getattr(module,k)) for k in dir(module)] + pdict = dict(_items) + else: + pdict = get_caller_module_dict(2) + + # Collect parser information from the dictionary + pinfo = ParserReflect(pdict,log=errorlog) + pinfo.get_all() + + if pinfo.error: + raise YaccError("Unable to build parser") + + # Check signature against table files (if any) + signature = pinfo.signature() + + # Read the tables + try: + lr = LRTable() + if picklefile: + read_signature = lr.read_pickle(picklefile) + else: + read_signature = lr.read_table(tabmodule) + if optimize or (read_signature == signature): + try: + lr.bind_callables(pinfo.pdict) + parser = LRParser(lr,pinfo.error_func) + parse = parser.parse + return parser + except Exception: + e = sys.exc_info()[1] + errorlog.warning("There was a problem loading the table file: %s", repr(e)) + except VersionError: + e = sys.exc_info() + errorlog.warning(str(e)) + except Exception: + pass + + if debuglog is None: + if debug: + debuglog = PlyLogger(open(debugfile,"w")) + else: + debuglog = NullLogger() + + debuglog.info("Created by PLY version %s (http://www.dabeaz.com/ply)", __version__) + + + errors = 0 + + # Validate the parser information + if pinfo.validate_all(): + raise YaccError("Unable to build parser") + + if not pinfo.error_func: + errorlog.warning("no p_error() function is defined") + + # Create a grammar object + grammar = Grammar(pinfo.tokens) + + # Set precedence level for terminals + for term, assoc, level in pinfo.preclist: + try: + grammar.set_precedence(term,assoc,level) + except GrammarError: + e = sys.exc_info()[1] + errorlog.warning("%s",str(e)) + + # Add productions to the grammar + for funcname, gram in pinfo.grammar: + file, line, prodname, syms = gram + try: + grammar.add_production(prodname,syms,funcname,file,line) + except GrammarError: + e = sys.exc_info()[1] + errorlog.error("%s",str(e)) + errors = 1 + + # Set the grammar start symbols + try: + if start is None: + grammar.set_start(pinfo.start) + else: + grammar.set_start(start) + except GrammarError: + e = sys.exc_info()[1] + errorlog.error(str(e)) + errors = 1 + + if errors: + raise YaccError("Unable to build parser") + + # Verify the grammar structure + undefined_symbols = grammar.undefined_symbols() + for sym, prod in undefined_symbols: + errorlog.error("%s:%d: Symbol '%s' used, but not defined as a token or a rule",prod.file,prod.line,sym) + errors = 1 + + unused_terminals = grammar.unused_terminals() + if unused_terminals: + debuglog.info("") + debuglog.info("Unused terminals:") + debuglog.info("") + for term in unused_terminals: + errorlog.warning("Token '%s' defined, but not used", term) + debuglog.info(" %s", term) + + # Print out all productions to the debug log + if debug: + debuglog.info("") + debuglog.info("Grammar") + debuglog.info("") + for n,p in enumerate(grammar.Productions): + debuglog.info("Rule %-5d %s", n, p) + + # Find unused non-terminals + unused_rules = grammar.unused_rules() + for prod in unused_rules: + errorlog.warning("%s:%d: Rule '%s' defined, but not used", prod.file, prod.line, prod.name) + + if len(unused_terminals) == 1: + errorlog.warning("There is 1 unused token") + if len(unused_terminals) > 1: + errorlog.warning("There are %d unused tokens", len(unused_terminals)) + + if len(unused_rules) == 1: + errorlog.warning("There is 1 unused rule") + if len(unused_rules) > 1: + errorlog.warning("There are %d unused rules", len(unused_rules)) + + if debug: + debuglog.info("") + debuglog.info("Terminals, with rules where they appear") + debuglog.info("") + terms = list(grammar.Terminals) + terms.sort() + for term in terms: + debuglog.info("%-20s : %s", term, " ".join([str(s) for s in grammar.Terminals[term]])) + + debuglog.info("") + debuglog.info("Nonterminals, with rules where they appear") + debuglog.info("") + nonterms = list(grammar.Nonterminals) + nonterms.sort() + for nonterm in nonterms: + debuglog.info("%-20s : %s", nonterm, " ".join([str(s) for s in grammar.Nonterminals[nonterm]])) + debuglog.info("") + + if check_recursion: + unreachable = grammar.find_unreachable() + for u in unreachable: + errorlog.warning("Symbol '%s' is unreachable",u) + + infinite = grammar.infinite_cycles() + for inf in infinite: + errorlog.error("Infinite recursion detected for symbol '%s'", inf) + errors = 1 + + unused_prec = grammar.unused_precedence() + for term, assoc in unused_prec: + errorlog.error("Precedence rule '%s' defined for unknown symbol '%s'", assoc, term) + errors = 1 + + if errors: + raise YaccError("Unable to build parser") + + # Run the LRGeneratedTable on the grammar + if debug: + errorlog.debug("Generating %s tables", method) + + lr = LRGeneratedTable(grammar,method,debuglog) + + if debug: + num_sr = len(lr.sr_conflicts) + + # Report shift/reduce and reduce/reduce conflicts + if num_sr == 1: + errorlog.warning("1 shift/reduce conflict") + elif num_sr > 1: + errorlog.warning("%d shift/reduce conflicts", num_sr) + + num_rr = len(lr.rr_conflicts) + if num_rr == 1: + errorlog.warning("1 reduce/reduce conflict") + elif num_rr > 1: + errorlog.warning("%d reduce/reduce conflicts", num_rr) + + # Write out conflicts to the output file + if debug and (lr.sr_conflicts or lr.rr_conflicts): + debuglog.warning("") + debuglog.warning("Conflicts:") + debuglog.warning("") + + for state, tok, resolution in lr.sr_conflicts: + debuglog.warning("shift/reduce conflict for %s in state %d resolved as %s", tok, state, resolution) + + already_reported = {} + for state, rule, rejected in lr.rr_conflicts: + if (state,id(rule),id(rejected)) in already_reported: + continue + debuglog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule) + debuglog.warning("rejected rule (%s) in state %d", rejected,state) + errorlog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule) + errorlog.warning("rejected rule (%s) in state %d", rejected, state) + already_reported[state,id(rule),id(rejected)] = 1 + + warned_never = [] + for state, rule, rejected in lr.rr_conflicts: + if not rejected.reduced and (rejected not in warned_never): + debuglog.warning("Rule (%s) is never reduced", rejected) + errorlog.warning("Rule (%s) is never reduced", rejected) + warned_never.append(rejected) + + # Write the table file if requested + if write_tables: + lr.write_table(tabmodule,outputdir,signature) + + # Write a pickled version of the tables + if picklefile: + lr.pickle_table(picklefile,signature) + + # Build the parser + lr.bind_callables(pinfo.pdict) + parser = LRParser(lr,pinfo.error_func) + + parse = parser.parse + return parser diff --git a/simulators/gem5/ext/ply/setup.py b/simulators/gem5/ext/ply/setup.py new file mode 100644 index 00000000..606b29cd --- /dev/null +++ b/simulators/gem5/ext/ply/setup.py @@ -0,0 +1,26 @@ +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + +setup(name = "ply", + description="Python Lex & Yacc", + long_description = """ +PLY is yet another implementation of lex and yacc for Python. Some notable +features include the fact that its implemented entirely in Python and it +uses LALR(1) parsing which is efficient and well suited for larger grammars. + +PLY provides most of the standard lex/yacc features including support for empty +productions, precedence rules, error recovery, and support for ambiguous grammars. + +PLY is extremely easy to use and provides very extensive error checking. +""", + license="""BSD""", + version = "3.2", + author = "David Beazley", + author_email = "dave@dabeaz.com", + maintainer = "David Beazley", + maintainer_email = "dave@dabeaz.com", + url = "http://www.dabeaz.com/ply/", + packages = ['ply'], + ) diff --git a/simulators/gem5/ext/ply/test/README b/simulators/gem5/ext/ply/test/README new file mode 100644 index 00000000..aac12b05 --- /dev/null +++ b/simulators/gem5/ext/ply/test/README @@ -0,0 +1,11 @@ +This directory mostly contains tests for various types of error +conditions. To run: + + $ python testlex.py . + $ python testyacc.py . + +The tests can also be run using the Python unittest module. + + $ python rununit.py + +The script 'cleanup.sh' cleans up this directory to its original state. diff --git a/simulators/gem5/ext/ply/test/calclex.py b/simulators/gem5/ext/ply/test/calclex.py new file mode 100644 index 00000000..67d245f1 --- /dev/null +++ b/simulators/gem5/ext/ply/test/calclex.py @@ -0,0 +1,49 @@ +# ----------------------------------------------------------------------------- +# calclex.py +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.lex as lex + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +lex.lex() + + + diff --git a/simulators/gem5/ext/ply/test/cleanup.sh b/simulators/gem5/ext/ply/test/cleanup.sh new file mode 100755 index 00000000..9db93683 --- /dev/null +++ b/simulators/gem5/ext/ply/test/cleanup.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -f *~ *.pyc *.pyo *.dif *.out + diff --git a/simulators/gem5/ext/ply/test/lex_closure.py b/simulators/gem5/ext/ply/test/lex_closure.py new file mode 100644 index 00000000..30ee6791 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_closure.py @@ -0,0 +1,54 @@ +# ----------------------------------------------------------------------------- +# lex_closure.py +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.lex as lex + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +def make_calc(): + + # Tokens + + t_PLUS = r'\+' + t_MINUS = r'-' + t_TIMES = r'\*' + t_DIVIDE = r'/' + t_EQUALS = r'=' + t_LPAREN = r'\(' + t_RPAREN = r'\)' + t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + + def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + + t_ignore = " \t" + + def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + + def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + + # Build the lexer + return lex.lex() + +make_calc() +lex.runmain(data="3+4") + + + diff --git a/simulators/gem5/ext/ply/test/lex_doc1.py b/simulators/gem5/ext/ply/test/lex_doc1.py new file mode 100644 index 00000000..8a2bfcce --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_doc1.py @@ -0,0 +1,26 @@ +# lex_doc1.py +# +# Missing documentation string + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +def t_NUMBER(t): + pass + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_dup1.py b/simulators/gem5/ext/ply/test/lex_dup1.py new file mode 100644 index 00000000..fd04cdb7 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_dup1.py @@ -0,0 +1,29 @@ +# lex_dup1.py +# +# Duplicated rule specifiers + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_NUMBER = r'\d+' + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_dup2.py b/simulators/gem5/ext/ply/test/lex_dup2.py new file mode 100644 index 00000000..870e5e7d --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_dup2.py @@ -0,0 +1,33 @@ +# lex_dup2.py +# +# Duplicated rule specifiers + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +def t_NUMBER(t): + r'\d+' + pass + +def t_NUMBER(t): + r'\d+' + pass + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_dup3.py b/simulators/gem5/ext/ply/test/lex_dup3.py new file mode 100644 index 00000000..94b5592e --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_dup3.py @@ -0,0 +1,31 @@ +# lex_dup3.py +# +# Duplicated rule specifiers + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_NUMBER(t): + r'\d+' + pass + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_empty.py b/simulators/gem5/ext/ply/test/lex_empty.py new file mode 100644 index 00000000..e0368bfa --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_empty.py @@ -0,0 +1,20 @@ +# lex_empty.py +# +# No rules defined + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_error1.py b/simulators/gem5/ext/ply/test/lex_error1.py new file mode 100644 index 00000000..4508a808 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_error1.py @@ -0,0 +1,24 @@ +# lex_error1.py +# +# Missing t_error() rule + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_error2.py b/simulators/gem5/ext/ply/test/lex_error2.py new file mode 100644 index 00000000..8040d390 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_error2.py @@ -0,0 +1,26 @@ +# lex_error2.py +# +# t_error defined, but not function + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_error = "foo" + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_error3.py b/simulators/gem5/ext/ply/test/lex_error3.py new file mode 100644 index 00000000..1feefb64 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_error3.py @@ -0,0 +1,27 @@ +# lex_error3.py +# +# t_error defined as function, but with wrong # args + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_error4.py b/simulators/gem5/ext/ply/test/lex_error4.py new file mode 100644 index 00000000..f4f48db1 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_error4.py @@ -0,0 +1,27 @@ +# lex_error4.py +# +# t_error defined as function, but too many args + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t,s): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_hedit.py b/simulators/gem5/ext/ply/test/lex_hedit.py new file mode 100644 index 00000000..34f15a17 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_hedit.py @@ -0,0 +1,47 @@ +# ----------------------------------------------------------------------------- +# hedit.py +# +# Paring of Fortran H Edit descriptions (Contributed by Pearu Peterson) +# +# These tokens can't be easily tokenized because they are of the following +# form: +# +# nHc1...cn +# +# where n is a positive integer and c1 ... cn are characters. +# +# This example shows how to modify the state of the lexer to parse +# such tokens +# ----------------------------------------------------------------------------- +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = ( + 'H_EDIT_DESCRIPTOR', + ) + +# Tokens +t_ignore = " \t\n" + +def t_H_EDIT_DESCRIPTOR(t): + r"\d+H.*" # This grabs all of the remaining text + i = t.value.index('H') + n = eval(t.value[:i]) + + # Adjust the tokenizing position + t.lexer.lexpos -= len(t.value) - (i+1+n) + t.value = t.value[i+1:i+1+n] + return t + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +lex.lex() +lex.runmain(data="3Habc 10Habcdefghij 2Hxy") + + + diff --git a/simulators/gem5/ext/ply/test/lex_ignore.py b/simulators/gem5/ext/ply/test/lex_ignore.py new file mode 100644 index 00000000..6c43b4cf --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_ignore.py @@ -0,0 +1,31 @@ +# lex_ignore.py +# +# Improperly specific ignore declaration + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_ignore(t): + ' \t' + pass + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_ignore2.py b/simulators/gem5/ext/ply/test/lex_ignore2.py new file mode 100644 index 00000000..f60987a6 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_ignore2.py @@ -0,0 +1,29 @@ +# lex_ignore2.py +# +# ignore declaration as a raw string + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_ignore = r' \t' + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_literal1.py b/simulators/gem5/ext/ply/test/lex_literal1.py new file mode 100644 index 00000000..db389c37 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_literal1.py @@ -0,0 +1,25 @@ +# lex_literal1.py +# +# Bad literal specification + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "NUMBER", + ] + +literals = ["+","-","**"] + +def t_NUMBER(t): + r'\d+' + return t + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_literal2.py b/simulators/gem5/ext/ply/test/lex_literal2.py new file mode 100644 index 00000000..b50b92cd --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_literal2.py @@ -0,0 +1,25 @@ +# lex_literal2.py +# +# Bad literal specification + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "NUMBER", + ] + +literals = 23 + +def t_NUMBER(t): + r'\d+' + return t + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_many_tokens.py b/simulators/gem5/ext/ply/test/lex_many_tokens.py new file mode 100644 index 00000000..77ae12ba --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_many_tokens.py @@ -0,0 +1,27 @@ +# lex_many_tokens.py +# +# Test lex's ability to handle a large number of tokens (beyond the +# 100-group limit of the re module) + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = ["TOK%d" % i for i in range(1000)] + +for tok in tokens: + if sys.version_info[0] < 3: + exec("t_%s = '%s:'" % (tok,tok)) + else: + exec("t_%s = '%s:'" % (tok,tok), globals()) + +t_ignore = " \t" + +def t_error(t): + pass + +lex.lex(optimize=1,lextab="manytab") +lex.runmain(data="TOK34: TOK143: TOK269: TOK372: TOK452: TOK561: TOK999:") + + diff --git a/simulators/gem5/ext/ply/test/lex_module.py b/simulators/gem5/ext/ply/test/lex_module.py new file mode 100644 index 00000000..8bdd3ed4 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_module.py @@ -0,0 +1,10 @@ +# lex_module.py +# + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex +import lex_module_import +lex.lex(module=lex_module_import) +lex.runmain(data="3+4") diff --git a/simulators/gem5/ext/ply/test/lex_module_import.py b/simulators/gem5/ext/ply/test/lex_module_import.py new file mode 100644 index 00000000..df420823 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_module_import.py @@ -0,0 +1,42 @@ +# ----------------------------------------------------------------------------- +# lex_module_import.py +# +# A lexer defined in a module, but built in lex_module.py +# ----------------------------------------------------------------------------- + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + diff --git a/simulators/gem5/ext/ply/test/lex_object.py b/simulators/gem5/ext/ply/test/lex_object.py new file mode 100644 index 00000000..7e9f389d --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_object.py @@ -0,0 +1,55 @@ +# ----------------------------------------------------------------------------- +# lex_object.py +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.lex as lex + +class CalcLexer: + tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + + # Tokens + + t_PLUS = r'\+' + t_MINUS = r'-' + t_TIMES = r'\*' + t_DIVIDE = r'/' + t_EQUALS = r'=' + t_LPAREN = r'\(' + t_RPAREN = r'\)' + t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + + def t_NUMBER(self,t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + + t_ignore = " \t" + + def t_newline(self,t): + r'\n+' + t.lineno += t.value.count("\n") + + def t_error(self,t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + + +calc = CalcLexer() + +# Build the lexer +lex.lex(object=calc) +lex.runmain(data="3+4") + + + + diff --git a/simulators/gem5/ext/ply/test/lex_opt_alias.py b/simulators/gem5/ext/ply/test/lex_opt_alias.py new file mode 100644 index 00000000..5d5ed4c4 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_opt_alias.py @@ -0,0 +1,54 @@ +# ----------------------------------------------------------------------------- +# lex_opt_alias.py +# +# Tests ability to match up functions with states, aliases, and +# lexing tables. +# ----------------------------------------------------------------------------- + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +tokens = ( + 'NAME','NUMBER', + ) + +states = (('instdef','inclusive'),('spam','exclusive')) + +literals = ['=','+','-','*','/', '(',')'] + +# Tokens + +def t_instdef_spam_BITS(t): + r'[01-]+' + return t + +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ANY_NUMBER = NUMBER + +t_ignore = " \t" +t_spam_ignore = t_ignore + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +t_spam_error = t_error + +# Build the lexer +import ply.lex as lex +lex.lex(optimize=1,lextab="aliastab") +lex.runmain(data="3+4") diff --git a/simulators/gem5/ext/ply/test/lex_optimize.py b/simulators/gem5/ext/ply/test/lex_optimize.py new file mode 100644 index 00000000..0e447e66 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_optimize.py @@ -0,0 +1,50 @@ +# ----------------------------------------------------------------------------- +# lex_optimize.py +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.lex as lex + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +lex.lex(optimize=1) +lex.runmain(data="3+4") + + + diff --git a/simulators/gem5/ext/ply/test/lex_optimize2.py b/simulators/gem5/ext/ply/test/lex_optimize2.py new file mode 100644 index 00000000..64555f63 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_optimize2.py @@ -0,0 +1,50 @@ +# ----------------------------------------------------------------------------- +# lex_optimize2.py +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.lex as lex + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +lex.lex(optimize=1,lextab="opt2tab") +lex.runmain(data="3+4") + + + diff --git a/simulators/gem5/ext/ply/test/lex_optimize3.py b/simulators/gem5/ext/ply/test/lex_optimize3.py new file mode 100644 index 00000000..c6c8cce6 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_optimize3.py @@ -0,0 +1,52 @@ +# ----------------------------------------------------------------------------- +# lex_optimize3.py +# +# Writes table in a subdirectory structure. +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.lex as lex + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print("Integer value too large %s" % t.value) + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +lex.lex(optimize=1,lextab="lexdir.sub.calctab",outputdir="lexdir/sub") +lex.runmain(data="3+4") + + + diff --git a/simulators/gem5/ext/ply/test/lex_re1.py b/simulators/gem5/ext/ply/test/lex_re1.py new file mode 100644 index 00000000..5be7aefc --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_re1.py @@ -0,0 +1,27 @@ +# lex_re1.py +# +# Bad regular expression in a string + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'(\d+' + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_re2.py b/simulators/gem5/ext/ply/test/lex_re2.py new file mode 100644 index 00000000..8dfb8e3f --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_re2.py @@ -0,0 +1,27 @@ +# lex_re2.py +# +# Regular expression rule matches empty string + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+?' +t_MINUS = r'-' +t_NUMBER = r'(\d+)' + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_re3.py b/simulators/gem5/ext/ply/test/lex_re3.py new file mode 100644 index 00000000..e1799253 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_re3.py @@ -0,0 +1,29 @@ +# lex_re3.py +# +# Regular expression rule matches empty string + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + "POUND", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'(\d+)' +t_POUND = r'#' + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_rule1.py b/simulators/gem5/ext/ply/test/lex_rule1.py new file mode 100644 index 00000000..0406c6f3 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_rule1.py @@ -0,0 +1,27 @@ +# lex_rule1.py +# +# Rule function with incorrect number of arguments + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = 1 + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_rule2.py b/simulators/gem5/ext/ply/test/lex_rule2.py new file mode 100644 index 00000000..1c29d873 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_rule2.py @@ -0,0 +1,29 @@ +# lex_rule2.py +# +# Rule function with incorrect number of arguments + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +def t_NUMBER(): + r'\d+' + return t + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_rule3.py b/simulators/gem5/ext/ply/test/lex_rule3.py new file mode 100644 index 00000000..9ea94da2 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_rule3.py @@ -0,0 +1,27 @@ +# lex_rule3.py +# +# Rule function with incorrect number of arguments + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +def t_NUMBER(t,s): + r'\d+' + return t + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state1.py b/simulators/gem5/ext/ply/test/lex_state1.py new file mode 100644 index 00000000..7528c915 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state1.py @@ -0,0 +1,40 @@ +# lex_state1.py +# +# Bad state declaration + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = 'comment' + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state2.py b/simulators/gem5/ext/ply/test/lex_state2.py new file mode 100644 index 00000000..3aef69ea --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state2.py @@ -0,0 +1,40 @@ +# lex_state2.py +# +# Bad state declaration + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = ('comment','example') + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state3.py b/simulators/gem5/ext/ply/test/lex_state3.py new file mode 100644 index 00000000..616e4847 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state3.py @@ -0,0 +1,42 @@ +# lex_state3.py +# +# Bad state declaration + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = ((comment, 'inclusive'), + ('example', 'exclusive')) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state4.py b/simulators/gem5/ext/ply/test/lex_state4.py new file mode 100644 index 00000000..18250161 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state4.py @@ -0,0 +1,41 @@ +# lex_state4.py +# +# Bad state declaration + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + + +states = (('comment', 'exclsive'),) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state5.py b/simulators/gem5/ext/ply/test/lex_state5.py new file mode 100644 index 00000000..4ce828e4 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state5.py @@ -0,0 +1,40 @@ +# lex_state5.py +# +# Bad state declaration + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = (('comment', 'exclusive'), + ('comment', 'exclusive')) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state_noerror.py b/simulators/gem5/ext/ply/test/lex_state_noerror.py new file mode 100644 index 00000000..90bbea87 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state_noerror.py @@ -0,0 +1,39 @@ +# lex_state_noerror.py +# +# Declaration of a state for which no rules are defined + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = (('comment', 'exclusive'),) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state_norule.py b/simulators/gem5/ext/ply/test/lex_state_norule.py new file mode 100644 index 00000000..64ec6d3e --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state_norule.py @@ -0,0 +1,40 @@ +# lex_state_norule.py +# +# Declaration of a state for which no rules are defined + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = (('comment', 'exclusive'), + ('example', 'exclusive')) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_state_try.py b/simulators/gem5/ext/ply/test/lex_state_try.py new file mode 100644 index 00000000..fd5ba222 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_state_try.py @@ -0,0 +1,45 @@ +# lex_state_try.py +# +# Declaration of a state for which no rules are defined + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = (('comment', 'exclusive'),) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_ignore = " \t" + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print("Entering comment state") + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print("comment body %s" % t) + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +t_comment_error = t_error +t_comment_ignore = t_ignore + +lex.lex() + +data = "3 + 4 /* This is a comment */ + 10" + +lex.runmain(data=data) diff --git a/simulators/gem5/ext/ply/test/lex_token1.py b/simulators/gem5/ext/ply/test/lex_token1.py new file mode 100644 index 00000000..6fca300b --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_token1.py @@ -0,0 +1,19 @@ +# lex_token1.py +# +# Tests for absence of tokens variable + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_token2.py b/simulators/gem5/ext/ply/test/lex_token2.py new file mode 100644 index 00000000..6e65ab0f --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_token2.py @@ -0,0 +1,22 @@ +# lex_token2.py +# +# Tests for tokens of wrong type + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = "PLUS MINUS NUMBER" + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_token3.py b/simulators/gem5/ext/ply/test/lex_token3.py new file mode 100644 index 00000000..636452ea --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_token3.py @@ -0,0 +1,24 @@ +# lex_token3.py +# +# tokens is right type, but is missing a token for one rule + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_token4.py b/simulators/gem5/ext/ply/test/lex_token4.py new file mode 100644 index 00000000..52947e9c --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_token4.py @@ -0,0 +1,26 @@ +# lex_token4.py +# +# Bad token name + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "-", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/lex_token5.py b/simulators/gem5/ext/ply/test/lex_token5.py new file mode 100644 index 00000000..ef7a3c50 --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_token5.py @@ -0,0 +1,31 @@ +# lex_token5.py +# +# Return a bad token name + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' + +def t_NUMBER(t): + r'\d+' + t.type = "NUM" + return t + +def t_error(t): + pass + +lex.lex() +lex.input("1234") +t = lex.token() + + diff --git a/simulators/gem5/ext/ply/test/lex_token_dup.py b/simulators/gem5/ext/ply/test/lex_token_dup.py new file mode 100644 index 00000000..384f4e9d --- /dev/null +++ b/simulators/gem5/ext/ply/test/lex_token_dup.py @@ -0,0 +1,29 @@ +# lex_token_dup.py +# +# Duplicate token name in tokens + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + "MINUS" + ] + +t_PLUS = r'\+' +t_MINUS = r'-' + +def t_NUMBER(t): + r'\d+' + return t + +def t_error(t): + pass + +lex.lex() + + diff --git a/simulators/gem5/ext/ply/test/testlex.py b/simulators/gem5/ext/ply/test/testlex.py new file mode 100755 index 00000000..606387d1 --- /dev/null +++ b/simulators/gem5/ext/ply/test/testlex.py @@ -0,0 +1,581 @@ +# testlex.py + +import unittest +try: + import StringIO +except ImportError: + import io as StringIO + +import sys +sys.path.insert(0,"..") +sys.tracebacklimit = 0 + +import ply.lex + +def check_expected(result,expected): + if sys.version_info[0] >= 3: + if isinstance(result,str): + result = result.encode('ascii') + if isinstance(expected,str): + expected = expected.encode('ascii') + resultlines = result.splitlines() + expectedlines = expected.splitlines() + + + if len(resultlines) != len(expectedlines): + return False + + for rline,eline in zip(resultlines,expectedlines): + if not rline.endswith(eline): + return False + return True + +def run_import(module): + code = "import "+module + exec(code) + del sys.modules[module] + +# Tests related to errors and warnings when building lexers +class LexErrorWarningTests(unittest.TestCase): + def setUp(self): + sys.stderr = StringIO.StringIO() + sys.stdout = StringIO.StringIO() + def tearDown(self): + sys.stderr = sys.__stderr__ + sys.stdout = sys.__stdout__ + def test_lex_doc1(self): + self.assertRaises(SyntaxError,run_import,"lex_doc1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_doc1.py:18: No regular expression defined for rule 't_NUMBER'\n")) + def test_lex_dup1(self): + self.assertRaises(SyntaxError,run_import,"lex_dup1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_dup1.py:20: Rule t_NUMBER redefined. Previously defined on line 18\n" )) + + def test_lex_dup2(self): + self.assertRaises(SyntaxError,run_import,"lex_dup2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_dup2.py:22: Rule t_NUMBER redefined. Previously defined on line 18\n" )) + + def test_lex_dup3(self): + self.assertRaises(SyntaxError,run_import,"lex_dup3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_dup3.py:20: Rule t_NUMBER redefined. Previously defined on line 18\n" )) + + def test_lex_empty(self): + self.assertRaises(SyntaxError,run_import,"lex_empty") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "No rules of the form t_rulename are defined\n" + "No rules defined for state 'INITIAL'\n")) + + def test_lex_error1(self): + run_import("lex_error1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "No t_error rule is defined\n")) + + def test_lex_error2(self): + self.assertRaises(SyntaxError,run_import,"lex_error2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Rule 't_error' must be defined as a function\n") + ) + + def test_lex_error3(self): + self.assertRaises(SyntaxError,run_import,"lex_error3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_error3.py:20: Rule 't_error' requires an argument\n")) + + def test_lex_error4(self): + self.assertRaises(SyntaxError,run_import,"lex_error4") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_error4.py:20: Rule 't_error' has too many arguments\n")) + + def test_lex_ignore(self): + self.assertRaises(SyntaxError,run_import,"lex_ignore") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_ignore.py:20: Rule 't_ignore' must be defined as a string\n")) + + def test_lex_ignore2(self): + run_import("lex_ignore2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "t_ignore contains a literal backslash '\\'\n")) + + + def test_lex_re1(self): + self.assertRaises(SyntaxError,run_import,"lex_re1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Invalid regular expression for rule 't_NUMBER'. unbalanced parenthesis\n")) + + def test_lex_re2(self): + self.assertRaises(SyntaxError,run_import,"lex_re2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Regular expression for rule 't_PLUS' matches empty string\n")) + + def test_lex_re3(self): + self.assertRaises(SyntaxError,run_import,"lex_re3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Invalid regular expression for rule 't_POUND'. unbalanced parenthesis\n" + "Make sure '#' in rule 't_POUND' is escaped with '\\#'\n")) + + def test_lex_rule1(self): + self.assertRaises(SyntaxError,run_import,"lex_rule1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "t_NUMBER not defined as a function or string\n")) + + def test_lex_rule2(self): + self.assertRaises(SyntaxError,run_import,"lex_rule2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_rule2.py:18: Rule 't_NUMBER' requires an argument\n")) + + def test_lex_rule3(self): + self.assertRaises(SyntaxError,run_import,"lex_rule3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "lex_rule3.py:18: Rule 't_NUMBER' has too many arguments\n")) + + + def test_lex_state1(self): + self.assertRaises(SyntaxError,run_import,"lex_state1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "states must be defined as a tuple or list\n")) + + def test_lex_state2(self): + self.assertRaises(SyntaxError,run_import,"lex_state2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Invalid state specifier 'comment'. Must be a tuple (statename,'exclusive|inclusive')\n" + "Invalid state specifier 'example'. Must be a tuple (statename,'exclusive|inclusive')\n")) + + def test_lex_state3(self): + self.assertRaises(SyntaxError,run_import,"lex_state3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "State name 1 must be a string\n" + "No rules defined for state 'example'\n")) + + def test_lex_state4(self): + self.assertRaises(SyntaxError,run_import,"lex_state4") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "State type for state comment must be 'inclusive' or 'exclusive'\n")) + + + def test_lex_state5(self): + self.assertRaises(SyntaxError,run_import,"lex_state5") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "State 'comment' already defined\n")) + + def test_lex_state_noerror(self): + run_import("lex_state_noerror") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "No error rule is defined for exclusive state 'comment'\n")) + + def test_lex_state_norule(self): + self.assertRaises(SyntaxError,run_import,"lex_state_norule") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "No rules defined for state 'example'\n")) + + def test_lex_token1(self): + self.assertRaises(SyntaxError,run_import,"lex_token1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "No token list is defined\n" + "Rule 't_NUMBER' defined for an unspecified token NUMBER\n" + "Rule 't_PLUS' defined for an unspecified token PLUS\n" + "Rule 't_MINUS' defined for an unspecified token MINUS\n" +)) + + def test_lex_token2(self): + self.assertRaises(SyntaxError,run_import,"lex_token2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "tokens must be a list or tuple\n" + "Rule 't_NUMBER' defined for an unspecified token NUMBER\n" + "Rule 't_PLUS' defined for an unspecified token PLUS\n" + "Rule 't_MINUS' defined for an unspecified token MINUS\n" +)) + + def test_lex_token3(self): + self.assertRaises(SyntaxError,run_import,"lex_token3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Rule 't_MINUS' defined for an unspecified token MINUS\n")) + + + def test_lex_token4(self): + self.assertRaises(SyntaxError,run_import,"lex_token4") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Bad token name '-'\n")) + + + def test_lex_token5(self): + try: + run_import("lex_token5") + except ply.lex.LexError: + e = sys.exc_info()[1] + self.assert_(check_expected(str(e),"lex_token5.py:19: Rule 't_NUMBER' returned an unknown token type 'NUM'")) + + def test_lex_token_dup(self): + run_import("lex_token_dup") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Token 'MINUS' multiply defined\n")) + + + def test_lex_literal1(self): + self.assertRaises(SyntaxError,run_import,"lex_literal1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Invalid literal '**'. Must be a single character\n")) + + def test_lex_literal2(self): + self.assertRaises(SyntaxError,run_import,"lex_literal2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Invalid literals specification. literals must be a sequence of characters\n")) + +import os +import subprocess +import shutil + +# Tests related to various build options associated with lexers +class LexBuildOptionTests(unittest.TestCase): + def setUp(self): + sys.stderr = StringIO.StringIO() + sys.stdout = StringIO.StringIO() + def tearDown(self): + sys.stderr = sys.__stderr__ + sys.stdout = sys.__stdout__ + try: + shutil.rmtree("lexdir") + except OSError: + pass + + def test_lex_module(self): + run_import("lex_module") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + + def test_lex_object(self): + run_import("lex_object") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + + def test_lex_closure(self): + run_import("lex_closure") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + def test_lex_optimize(self): + try: + os.remove("lextab.py") + except OSError: + pass + try: + os.remove("lextab.pyc") + except OSError: + pass + try: + os.remove("lextab.pyo") + except OSError: + pass + run_import("lex_optimize") + + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("lextab.py")) + + + p = subprocess.Popen([sys.executable,'-O','lex_optimize.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("lextab.pyo")) + + os.remove("lextab.pyo") + p = subprocess.Popen([sys.executable,'-OO','lex_optimize.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("lextab.pyo")) + try: + os.remove("lextab.py") + except OSError: + pass + try: + os.remove("lextab.pyc") + except OSError: + pass + try: + os.remove("lextab.pyo") + except OSError: + pass + + def test_lex_optimize2(self): + try: + os.remove("opt2tab.py") + except OSError: + pass + try: + os.remove("opt2tab.pyc") + except OSError: + pass + try: + os.remove("opt2tab.pyo") + except OSError: + pass + run_import("lex_optimize2") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("opt2tab.py")) + + p = subprocess.Popen([sys.executable,'-O','lex_optimize2.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("opt2tab.pyo")) + os.remove("opt2tab.pyo") + p = subprocess.Popen([sys.executable,'-OO','lex_optimize2.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("opt2tab.pyo")) + try: + os.remove("opt2tab.py") + except OSError: + pass + try: + os.remove("opt2tab.pyc") + except OSError: + pass + try: + os.remove("opt2tab.pyo") + except OSError: + pass + + def test_lex_optimize3(self): + try: + shutil.rmtree("lexdir") + except OSError: + pass + + os.mkdir("lexdir") + os.mkdir("lexdir/sub") + open("lexdir/__init__.py","w").write("") + open("lexdir/sub/__init__.py","w").write("") + run_import("lex_optimize3") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("lexdir/sub/calctab.py")) + + p = subprocess.Popen([sys.executable,'-O','lex_optimize3.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("lexdir/sub/calctab.pyo")) + os.remove("lexdir/sub/calctab.pyo") + p = subprocess.Popen([sys.executable,'-OO','lex_optimize3.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(PLUS,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("lexdir/sub/calctab.pyo")) + try: + shutil.rmtree("lexdir") + except OSError: + pass + + def test_lex_opt_alias(self): + try: + os.remove("aliastab.py") + except OSError: + pass + try: + os.remove("aliastab.pyc") + except OSError: + pass + try: + os.remove("aliastab.pyo") + except OSError: + pass + run_import("lex_opt_alias") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(+,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("aliastab.py")) + + p = subprocess.Popen([sys.executable,'-O','lex_opt_alias.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(+,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("aliastab.pyo")) + os.remove("aliastab.pyo") + p = subprocess.Popen([sys.executable,'-OO','lex_opt_alias.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(NUMBER,3,1,0)\n" + "(+,'+',1,1)\n" + "(NUMBER,4,1,2)\n")) + self.assert_(os.path.exists("aliastab.pyo")) + try: + os.remove("aliastab.py") + except OSError: + pass + try: + os.remove("aliastab.pyc") + except OSError: + pass + try: + os.remove("aliastab.pyo") + except OSError: + pass + + def test_lex_many_tokens(self): + try: + os.remove("manytab.py") + except OSError: + pass + try: + os.remove("manytab.pyc") + except OSError: + pass + try: + os.remove("manytab.pyo") + except OSError: + pass + run_import("lex_many_tokens") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(TOK34,'TOK34:',1,0)\n" + "(TOK143,'TOK143:',1,7)\n" + "(TOK269,'TOK269:',1,15)\n" + "(TOK372,'TOK372:',1,23)\n" + "(TOK452,'TOK452:',1,31)\n" + "(TOK561,'TOK561:',1,39)\n" + "(TOK999,'TOK999:',1,47)\n" + )) + + self.assert_(os.path.exists("manytab.py")) + + p = subprocess.Popen([sys.executable,'-O','lex_many_tokens.py'], + stdout=subprocess.PIPE) + result = p.stdout.read() + self.assert_(check_expected(result, + "(TOK34,'TOK34:',1,0)\n" + "(TOK143,'TOK143:',1,7)\n" + "(TOK269,'TOK269:',1,15)\n" + "(TOK372,'TOK372:',1,23)\n" + "(TOK452,'TOK452:',1,31)\n" + "(TOK561,'TOK561:',1,39)\n" + "(TOK999,'TOK999:',1,47)\n" + )) + + self.assert_(os.path.exists("manytab.pyo")) + os.remove("manytab.pyo") + try: + os.remove("manytab.py") + except OSError: + pass + try: + os.remove("manytab.pyc") + except OSError: + pass + try: + os.remove("manytab.pyo") + except OSError: + pass + +# Tests related to run-time behavior of lexers +class LexRunTests(unittest.TestCase): + def setUp(self): + sys.stderr = StringIO.StringIO() + sys.stdout = StringIO.StringIO() + def tearDown(self): + sys.stderr = sys.__stderr__ + sys.stdout = sys.__stdout__ + + def test_lex_hedit(self): + run_import("lex_hedit") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(H_EDIT_DESCRIPTOR,'abc',1,0)\n" + "(H_EDIT_DESCRIPTOR,'abcdefghij',1,6)\n" + "(H_EDIT_DESCRIPTOR,'xy',1,20)\n")) + + def test_lex_state_try(self): + run_import("lex_state_try") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "(NUMBER,'3',1,0)\n" + "(PLUS,'+',1,2)\n" + "(NUMBER,'4',1,4)\n" + "Entering comment state\n" + "comment body LexToken(body_part,'This is a comment */',1,9)\n" + "(PLUS,'+',1,30)\n" + "(NUMBER,'10',1,32)\n" + )) + + + +unittest.main() diff --git a/simulators/gem5/ext/ply/test/testyacc.py b/simulators/gem5/ext/ply/test/testyacc.py new file mode 100644 index 00000000..cc53b6d8 --- /dev/null +++ b/simulators/gem5/ext/ply/test/testyacc.py @@ -0,0 +1,324 @@ +# testyacc.py + +import unittest +try: + import StringIO +except ImportError: + import io as StringIO + +import sys +import os + +sys.path.insert(0,"..") +sys.tracebacklimit = 0 + +import ply.yacc + +def check_expected(result,expected): + resultlines = [] + for line in result.splitlines(): + if line.startswith("WARNING: "): + line = line[9:] + elif line.startswith("ERROR: "): + line = line[7:] + resultlines.append(line) + + expectedlines = expected.splitlines() + if len(resultlines) != len(expectedlines): + return False + for rline,eline in zip(resultlines,expectedlines): + if not rline.endswith(eline): + return False + return True + +def run_import(module): + code = "import "+module + exec(code) + del sys.modules[module] + +# Tests related to errors and warnings when building parsers +class YaccErrorWarningTests(unittest.TestCase): + def setUp(self): + sys.stderr = StringIO.StringIO() + sys.stdout = StringIO.StringIO() + try: + os.remove("parsetab.py") + os.remove("parsetab.pyc") + except OSError: + pass + + def tearDown(self): + sys.stderr = sys.__stderr__ + sys.stdout = sys.__stdout__ + def test_yacc_badargs(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badargs") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_badargs.py:23: Rule 'p_statement_assign' has too many arguments\n" + "yacc_badargs.py:27: Rule 'p_statement_expr' requires an argument\n" + )) + def test_yacc_badid(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badid") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_badid.py:32: Illegal name 'bad&rule' in rule 'statement'\n" + "yacc_badid.py:36: Illegal rule name 'bad&rule'\n" + )) + + def test_yacc_badprec(self): + try: + run_import("yacc_badprec") + except ply.yacc.YaccError: + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "precedence must be a list or tuple\n" + )) + def test_yacc_badprec2(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badprec2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Bad precedence table\n" + )) + + def test_yacc_badprec3(self): + run_import("yacc_badprec3") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Precedence already specified for terminal 'MINUS'\n" + "Generating LALR tables\n" + + )) + + def test_yacc_badrule(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badrule") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_badrule.py:24: Syntax error. Expected ':'\n" + "yacc_badrule.py:28: Syntax error in rule 'statement'\n" + "yacc_badrule.py:33: Syntax error. Expected ':'\n" + "yacc_badrule.py:42: Syntax error. Expected ':'\n" + )) + + def test_yacc_badtok(self): + try: + run_import("yacc_badtok") + except ply.yacc.YaccError: + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "tokens must be a list or tuple\n")) + + def test_yacc_dup(self): + run_import("yacc_dup") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_dup.py:27: Function p_statement redefined. Previously defined on line 23\n" + "Token 'EQUALS' defined, but not used\n" + "There is 1 unused token\n" + "Generating LALR tables\n" + + )) + def test_yacc_error1(self): + try: + run_import("yacc_error1") + except ply.yacc.YaccError: + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_error1.py:61: p_error() requires 1 argument\n")) + + def test_yacc_error2(self): + try: + run_import("yacc_error2") + except ply.yacc.YaccError: + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_error2.py:61: p_error() requires 1 argument\n")) + + def test_yacc_error3(self): + try: + run_import("yacc_error3") + except ply.yacc.YaccError: + e = sys.exc_info()[1] + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "'p_error' defined, but is not a function or method\n")) + + def test_yacc_error4(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_error4") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_error4.py:62: Illegal rule name 'error'. Already defined as a token\n" + )) + + def test_yacc_inf(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_inf") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Token 'NUMBER' defined, but not used\n" + "There is 1 unused token\n" + "Infinite recursion detected for symbol 'statement'\n" + "Infinite recursion detected for symbol 'expression'\n" + )) + def test_yacc_literal(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_literal") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_literal.py:36: Literal token '**' in rule 'expression' may only be a single character\n" + )) + def test_yacc_misplaced(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_misplaced") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_misplaced.py:32: Misplaced '|'\n" + )) + + def test_yacc_missing1(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_missing1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_missing1.py:24: Symbol 'location' used, but not defined as a token or a rule\n" + )) + + def test_yacc_nested(self): + run_import("yacc_nested") + result = sys.stdout.getvalue() + self.assert_(check_expected(result, + "A\n" + "A\n" + "A\n", + )) + + def test_yacc_nodoc(self): + run_import("yacc_nodoc") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_nodoc.py:27: No documentation string specified in function 'p_statement_expr' (ignored)\n" + "Generating LALR tables\n" + )) + + def test_yacc_noerror(self): + run_import("yacc_noerror") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "no p_error() function is defined\n" + "Generating LALR tables\n" + )) + + def test_yacc_nop(self): + run_import("yacc_nop") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_nop.py:27: Possible grammar rule 'statement_expr' defined without p_ prefix\n" + "Generating LALR tables\n" + )) + + def test_yacc_notfunc(self): + run_import("yacc_notfunc") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "'p_statement_assign' not defined as a function\n" + "Token 'EQUALS' defined, but not used\n" + "There is 1 unused token\n" + "Generating LALR tables\n" + )) + def test_yacc_notok(self): + try: + run_import("yacc_notok") + except ply.yacc.YaccError: + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "No token list is defined\n")) + + def test_yacc_rr(self): + run_import("yacc_rr") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Generating LALR tables\n" + "1 reduce/reduce conflict\n" + "reduce/reduce conflict in state 15 resolved using rule (statement -> NAME EQUALS NUMBER)\n" + "rejected rule (expression -> NUMBER) in state 15\n" + + )) + + def test_yacc_rr_unused(self): + run_import("yacc_rr_unused") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "no p_error() function is defined\n" + "Generating LALR tables\n" + "3 reduce/reduce conflicts\n" + "reduce/reduce conflict in state 1 resolved using rule (rule3 -> A)\n" + "rejected rule (rule4 -> A) in state 1\n" + "reduce/reduce conflict in state 1 resolved using rule (rule3 -> A)\n" + "rejected rule (rule5 -> A) in state 1\n" + "reduce/reduce conflict in state 1 resolved using rule (rule4 -> A)\n" + "rejected rule (rule5 -> A) in state 1\n" + "Rule (rule5 -> A) is never reduced\n" + )) + + def test_yacc_simple(self): + run_import("yacc_simple") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Generating LALR tables\n" + )) + def test_yacc_sr(self): + run_import("yacc_sr") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Generating LALR tables\n" + "20 shift/reduce conflicts\n" + )) + + def test_yacc_term1(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_term1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_term1.py:24: Illegal rule name 'NUMBER'. Already defined as a token\n" + )) + + def test_yacc_unused(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_unused") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_unused.py:62: Symbol 'COMMA' used, but not defined as a token or a rule\n" + "Symbol 'COMMA' is unreachable\n" + "Symbol 'exprlist' is unreachable\n" + )) + def test_yacc_unused_rule(self): + run_import("yacc_unused_rule") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_unused_rule.py:62: Rule 'integer' defined, but not used\n" + "There is 1 unused rule\n" + "Symbol 'integer' is unreachable\n" + "Generating LALR tables\n" + )) + + def test_yacc_uprec(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_uprec") + result = sys.stderr.getvalue() + print repr(result) + self.assert_(check_expected(result, + "yacc_uprec.py:37: Nothing known about the precedence of 'UMINUS'\n" + )) + + def test_yacc_uprec2(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_uprec2") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "yacc_uprec2.py:37: Syntax error. Nothing follows %prec\n" + )) + + def test_yacc_prec1(self): + self.assertRaises(ply.yacc.YaccError,run_import,"yacc_prec1") + result = sys.stderr.getvalue() + self.assert_(check_expected(result, + "Precedence rule 'left' defined for unknown symbol '+'\n" + "Precedence rule 'left' defined for unknown symbol '*'\n" + "Precedence rule 'left' defined for unknown symbol '-'\n" + "Precedence rule 'left' defined for unknown symbol '/'\n" + )) + + + +unittest.main() diff --git a/simulators/gem5/ext/ply/test/yacc_badargs.py b/simulators/gem5/ext/ply/test/yacc_badargs.py new file mode 100644 index 00000000..9a1d03f2 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badargs.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_badargs.py +# +# Rules with wrong # args +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t,s): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_badid.py b/simulators/gem5/ext/ply/test/yacc_badid.py new file mode 100644 index 00000000..e4b9f5ee --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badid.py @@ -0,0 +1,77 @@ +# ----------------------------------------------------------------------------- +# yacc_badid.py +# +# Attempt to define a rule with a bad-identifier name +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_statement_expr2(t): + 'statement : bad&rule' + pass + +def p_badrule(t): + 'bad&rule : expression' + pass + + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + pass + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_badprec.py b/simulators/gem5/ext/ply/test/yacc_badprec.py new file mode 100644 index 00000000..3013bb62 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badprec.py @@ -0,0 +1,64 @@ +# ----------------------------------------------------------------------------- +# yacc_badprec.py +# +# Bad precedence specifier +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = "blah" + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_badprec2.py b/simulators/gem5/ext/ply/test/yacc_badprec2.py new file mode 100644 index 00000000..83093b42 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badprec2.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_badprec2.py +# +# Bad precedence +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + 42, + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_badprec3.py b/simulators/gem5/ext/ply/test/yacc_badprec3.py new file mode 100644 index 00000000..d925ecd5 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badprec3.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_badprec3.py +# +# Bad precedence +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE','MINUS'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_badrule.py b/simulators/gem5/ext/ply/test/yacc_badrule.py new file mode 100644 index 00000000..92af6460 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badrule.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_badrule.py +# +# Syntax problems in the rule strings +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression: MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_badtok.py b/simulators/gem5/ext/ply/test/yacc_badtok.py new file mode 100644 index 00000000..fc4afe19 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_badtok.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_badtok.py +# +# A grammar, but tokens is a bad datatype +# ----------------------------------------------------------------------------- + +import sys +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +tokens = "Hello" + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_dup.py b/simulators/gem5/ext/ply/test/yacc_dup.py new file mode 100644 index 00000000..309ba329 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_dup.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_dup.py +# +# Duplicated rule name +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_error1.py b/simulators/gem5/ext/ply/test/yacc_error1.py new file mode 100644 index 00000000..10ac6a9c --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_error1.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_error1.py +# +# Bad p_error() function +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t,s): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_error2.py b/simulators/gem5/ext/ply/test/yacc_error2.py new file mode 100644 index 00000000..75914180 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_error2.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_error2.py +# +# Bad p_error() function +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_error3.py b/simulators/gem5/ext/ply/test/yacc_error3.py new file mode 100644 index 00000000..4604a48b --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_error3.py @@ -0,0 +1,67 @@ +# ----------------------------------------------------------------------------- +# yacc_error3.py +# +# Bad p_error() function +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +p_error = "blah" + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_error4.py b/simulators/gem5/ext/ply/test/yacc_error4.py new file mode 100644 index 00000000..9c550cd8 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_error4.py @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# yacc_error4.py +# +# Attempt to define a rule named 'error' +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error_handler(t): + 'error : NAME' + pass + +def p_error(t): + pass + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_inf.py b/simulators/gem5/ext/ply/test/yacc_inf.py new file mode 100644 index 00000000..efd3612a --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_inf.py @@ -0,0 +1,56 @@ +# ----------------------------------------------------------------------------- +# yacc_inf.py +# +# Infinite recursion +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_literal.py b/simulators/gem5/ext/ply/test/yacc_literal.py new file mode 100644 index 00000000..0d628035 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_literal.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_literal.py +# +# Grammar with bad literal characters +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','+','-'), + ('left','*','/'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression '+' expression + | expression '-' expression + | expression '*' expression + | expression '/' expression + | expression '**' expression ''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_misplaced.py b/simulators/gem5/ext/ply/test/yacc_misplaced.py new file mode 100644 index 00000000..9159b010 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_misplaced.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_misplaced.py +# +# A misplaced | in grammar rules +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + ''' | expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_missing1.py b/simulators/gem5/ext/ply/test/yacc_missing1.py new file mode 100644 index 00000000..d1b51059 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_missing1.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_missing1.py +# +# Grammar with a missing rule +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : location EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_nested.py b/simulators/gem5/ext/ply/test/yacc_nested.py new file mode 100644 index 00000000..a1b061e7 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_nested.py @@ -0,0 +1,33 @@ +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") + +from ply import lex, yacc + +t_A = 'A' +t_B = 'B' +t_C = 'C' + +tokens = ('A', 'B', 'C') + +the_lexer = lex.lex() + +def t_error(t): + pass + +def p_error(p): + pass + +def p_start(t): + '''start : A nest C''' + pass + +def p_nest(t): + '''nest : B''' + print(t[-1]) + +the_parser = yacc.yacc(debug = False, write_tables = False) + +the_parser.parse('ABC', the_lexer) +the_parser.parse('ABC', the_lexer, tracking=True) +the_parser.parse('ABC', the_lexer, tracking=True, debug=1) diff --git a/simulators/gem5/ext/ply/test/yacc_nodoc.py b/simulators/gem5/ext/ply/test/yacc_nodoc.py new file mode 100644 index 00000000..0f61920a --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_nodoc.py @@ -0,0 +1,67 @@ +# ----------------------------------------------------------------------------- +# yacc_nodoc.py +# +# Rule with a missing doc-string +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_noerror.py b/simulators/gem5/ext/ply/test/yacc_noerror.py new file mode 100644 index 00000000..b38c7581 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_noerror.py @@ -0,0 +1,66 @@ +# ----------------------------------------------------------------------------- +# yacc_noerror.py +# +# No p_error() rule defined. +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_nop.py b/simulators/gem5/ext/ply/test/yacc_nop.py new file mode 100644 index 00000000..789a9cfa --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_nop.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_nop.py +# +# Possible grammar rule defined without p_ prefix +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_notfunc.py b/simulators/gem5/ext/ply/test/yacc_notfunc.py new file mode 100644 index 00000000..5093a744 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_notfunc.py @@ -0,0 +1,66 @@ +# ----------------------------------------------------------------------------- +# yacc_notfunc.py +# +# p_rule not defined as a function +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +p_statement_assign = "Blah" + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_notok.py b/simulators/gem5/ext/ply/test/yacc_notok.py new file mode 100644 index 00000000..cff55a8d --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_notok.py @@ -0,0 +1,67 @@ +# ----------------------------------------------------------------------------- +# yacc_notok.py +# +# A grammar, but we forgot to import the tokens list +# ----------------------------------------------------------------------------- + +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_prec1.py b/simulators/gem5/ext/ply/test/yacc_prec1.py new file mode 100644 index 00000000..2ca6afc0 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_prec1.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_prec1.py +# +# Tests case where precedence specifier doesn't match up to terminals +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','+','-'), + ('left','*','/'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_rr.py b/simulators/gem5/ext/ply/test/yacc_rr.py new file mode 100644 index 00000000..e7336c2f --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_rr.py @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# yacc_rr.py +# +# A grammar with a reduce/reduce conflict +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_assign_2(t): + 'statement : NAME EQUALS NUMBER' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_rr_unused.py b/simulators/gem5/ext/ply/test/yacc_rr_unused.py new file mode 100644 index 00000000..1ca5f7e5 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_rr_unused.py @@ -0,0 +1,30 @@ +# ----------------------------------------------------------------------------- +# yacc_rr_unused.py +# +# A grammar with reduce/reduce conflicts and a rule that never +# gets reduced. +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +tokens = ('A', 'B', 'C') + +def p_grammar(p): + ''' + rule1 : rule2 B + | rule2 C + + rule2 : rule3 B + | rule4 + | rule5 + + rule3 : A + + rule4 : A + + rule5 : A + ''' + +yacc.yacc() diff --git a/simulators/gem5/ext/ply/test/yacc_simple.py b/simulators/gem5/ext/ply/test/yacc_simple.py new file mode 100644 index 00000000..bd989f4d --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_simple.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_simple.py +# +# A simple, properly specifier grammar +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_sr.py b/simulators/gem5/ext/ply/test/yacc_sr.py new file mode 100644 index 00000000..69a1e9c7 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_sr.py @@ -0,0 +1,63 @@ +# ----------------------------------------------------------------------------- +# yacc_sr.py +# +# A grammar with shift-reduce conflicts +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_term1.py b/simulators/gem5/ext/ply/test/yacc_term1.py new file mode 100644 index 00000000..eaa36e9d --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_term1.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_term1.py +# +# Terminal used on the left-hand-side +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'NUMBER : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_unused.py b/simulators/gem5/ext/ply/test/yacc_unused.py new file mode 100644 index 00000000..55b677b1 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_unused.py @@ -0,0 +1,77 @@ +# ----------------------------------------------------------------------------- +# yacc_unused.py +# +# A grammar with an unused rule +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_expr_list(t): + 'exprlist : exprlist COMMA expression' + pass + +def p_expr_list_2(t): + 'exprlist : expression' + pass + + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_unused_rule.py b/simulators/gem5/ext/ply/test/yacc_unused_rule.py new file mode 100644 index 00000000..4868ef86 --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_unused_rule.py @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# yacc_unused_rule.py +# +# Grammar with an unused rule +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_integer(t): + 'integer : NUMBER' + t[0] = t[1] + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_uprec.py b/simulators/gem5/ext/ply/test/yacc_uprec.py new file mode 100644 index 00000000..569adb8f --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_uprec.py @@ -0,0 +1,63 @@ +# ----------------------------------------------------------------------------- +# yacc_uprec.py +# +# A grammar with a bad %prec specifier +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/ply/test/yacc_uprec2.py b/simulators/gem5/ext/ply/test/yacc_uprec2.py new file mode 100644 index 00000000..73274bfb --- /dev/null +++ b/simulators/gem5/ext/ply/test/yacc_uprec2.py @@ -0,0 +1,63 @@ +# ----------------------------------------------------------------------------- +# yacc_uprec2.py +# +# A grammar with a bad %prec specifier +# ----------------------------------------------------------------------------- +import sys + +if ".." not in sys.path: sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print(t[1]) + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[2] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print("Undefined name '%s'" % t[1]) + t[0] = 0 + +def p_error(t): + print("Syntax error at '%s'" % t.value) + +yacc.yacc() + + + + diff --git a/simulators/gem5/ext/x11keysym/keysym.h b/simulators/gem5/ext/x11keysym/keysym.h new file mode 100644 index 00000000..319ce499 --- /dev/null +++ b/simulators/gem5/ext/x11keysym/keysym.h @@ -0,0 +1,76 @@ +/* $Xorg: keysym.h,v 1.4 2001/02/09 02:03:23 xorgcvs Exp $ */ + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/keysym.h,v 1.3 2001/01/17 17:53:12 dawes Exp $ */ + +/* default keysyms */ +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_LATIN8 +#define XK_LATIN9 +#define XK_CAUCASUS +#define XK_GREEK +#define XK_KATAKANA +#define XK_ARABIC +#define XK_CYRILLIC +#define XK_HEBREW +#define XK_THAI +#define XK_KOREAN +#define XK_ARMENIAN +#define XK_GEORGIAN +#define XK_VIETNAMESE +#define XK_CURRENCY +#define XK_MATHEMATICAL +#define XK_BRAILLE + +#include "x11keysym/keysymdef.h" + diff --git a/simulators/gem5/ext/x11keysym/keysymdef.h b/simulators/gem5/ext/x11keysym/keysymdef.h new file mode 100644 index 00000000..b3ade4d9 --- /dev/null +++ b/simulators/gem5/ext/x11keysym/keysymdef.h @@ -0,0 +1,2358 @@ +/* $Xorg: keysymdef.h,v 1.4 2001/02/09 02:03:23 $ */ + +/*********************************************************** +Copyright 1987, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: $ */ + +/* + * The "X11 Window System Protocol" standard defines in Appendix A the + * keysym codes. These 29-bit integer values identify characters or + * functions associated with each key (e.g., via the visible + * engraving) of a keyboard layout. This file assigns mnemonic macro + * names for these keysyms. + * + * This file is also compiled (by xc/lib/X11/util/makekeys.c) into + * hash tables that can be accessed with X11 library functions such as + * XStringToKeysym() and XKeysymToString(). + * + * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode + * character, this is noted in a comment that provides both the U+xxxx + * Unicode position, as well as the official Unicode name of the + * character. + * + * Where the correspondence is either not one-to-one or semantically + * unclear, the Unicode position and name are enclosed in + * parentheses. Such legacy keysyms should be considered deprecated + * and are not recommended for use in future keyboard mappings. + * + * For any future extension of the keysyms with characters already + * found in ISO 10646 / Unicode, the following algorithm shall be + * used. The new keysym code position will simply be the character's + * Unicode number plus 0x01000000. The keysym values in the range + * 0x01000100 to 0x0110ffff are reserved to represent Unicode + * characters in the range U+0100 to U+10FFFF. + * + * While most newer Unicode-based X11 clients do already accept + * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it + * will remain necessary for clients -- in the interest of + * compatibility with existing servers -- to also understand the + * existing legacy keysym values in the range 0x0100 to 0x20ff. + * + * Where several mnemonic names are defined for the same keysym in this + * file, all but the first one listed should be considered deprecated. + * + * Mnemonic names for keysyms are defined in this file with lines + * that match one of these Perl regular expressions: + * + * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\* U+([0-9A-F]{4,6}) (.*) \*\/\s*$/ + * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\(U+([0-9A-F]{4,6}) (.*)\)\*\/\s*$/ + * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/ + * + * When adding new keysyms to this file, do not forget to also update the + * mappings in xc/lib/X11/KeyBind.c and the protocol specification in + * xc/doc/specs/XProtocol/X11.keysyms. + */ + +/* + * Now that the Xorg code base is managed in Git repositories, the KeyBind.c + * and X11.keysyms files mentioned in the last comment block are located at: + * + * src/KeyBind.c in the repo git://anongit.freedesktop.org/xorg/lib/libX11 + * specs/XProtocol/X11.keysyms in the repo git://anongit.freedesktop.org/xorg/doc/xorg-docs + */ + +#define XK_VoidSymbol 0xffffff /* Void symbol */ + +#ifdef XK_MISCELLANY +/* + * TTY function keys, cleverly chosen to map to ASCII, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code). + */ + +#define XK_BackSpace 0xff08 /* Back space, back char */ +#define XK_Tab 0xff09 +#define XK_Linefeed 0xff0a /* Linefeed, LF */ +#define XK_Clear 0xff0b +#define XK_Return 0xff0d /* Return, enter */ +#define XK_Pause 0xff13 /* Pause, hold */ +#define XK_Scroll_Lock 0xff14 +#define XK_Sys_Req 0xff15 +#define XK_Escape 0xff1b +#define XK_Delete 0xffff /* Delete, rubout */ + + + +/* International & multi-key character composition */ + +#define XK_Multi_key 0xff20 /* Multi-key character compose */ +#define XK_Codeinput 0xff37 +#define XK_SingleCandidate 0xff3c +#define XK_MultipleCandidate 0xff3d +#define XK_PreviousCandidate 0xff3e + +/* Japanese keyboard support */ + +#define XK_Kanji 0xff21 /* Kanji, Kanji convert */ +#define XK_Muhenkan 0xff22 /* Cancel Conversion */ +#define XK_Henkan_Mode 0xff23 /* Start/Stop Conversion */ +#define XK_Henkan 0xff23 /* Alias for Henkan_Mode */ +#define XK_Romaji 0xff24 /* to Romaji */ +#define XK_Hiragana 0xff25 /* to Hiragana */ +#define XK_Katakana 0xff26 /* to Katakana */ +#define XK_Hiragana_Katakana 0xff27 /* Hiragana/Katakana toggle */ +#define XK_Zenkaku 0xff28 /* to Zenkaku */ +#define XK_Hankaku 0xff29 /* to Hankaku */ +#define XK_Zenkaku_Hankaku 0xff2a /* Zenkaku/Hankaku toggle */ +#define XK_Touroku 0xff2b /* Add to Dictionary */ +#define XK_Massyo 0xff2c /* Delete from Dictionary */ +#define XK_Kana_Lock 0xff2d /* Kana Lock */ +#define XK_Kana_Shift 0xff2e /* Kana Shift */ +#define XK_Eisu_Shift 0xff2f /* Alphanumeric Shift */ +#define XK_Eisu_toggle 0xff30 /* Alphanumeric toggle */ +#define XK_Kanji_Bangou 0xff37 /* Codeinput */ +#define XK_Zen_Koho 0xff3d /* Multiple/All Candidate(s) */ +#define XK_Mae_Koho 0xff3e /* Previous Candidate */ + +/* 0xff31 thru 0xff3f are under XK_KOREAN */ + +/* Cursor control & motion */ + +#define XK_Home 0xff50 +#define XK_Left 0xff51 /* Move left, left arrow */ +#define XK_Up 0xff52 /* Move up, up arrow */ +#define XK_Right 0xff53 /* Move right, right arrow */ +#define XK_Down 0xff54 /* Move down, down arrow */ +#define XK_Prior 0xff55 /* Prior, previous */ +#define XK_Page_Up 0xff55 +#define XK_Next 0xff56 /* Next */ +#define XK_Page_Down 0xff56 +#define XK_End 0xff57 /* EOL */ +#define XK_Begin 0xff58 /* BOL */ + + +/* Misc functions */ + +#define XK_Select 0xff60 /* Select, mark */ +#define XK_Print 0xff61 +#define XK_Execute 0xff62 /* Execute, run, do */ +#define XK_Insert 0xff63 /* Insert, insert here */ +#define XK_Undo 0xff65 +#define XK_Redo 0xff66 /* Redo, again */ +#define XK_Menu 0xff67 +#define XK_Find 0xff68 /* Find, search */ +#define XK_Cancel 0xff69 /* Cancel, stop, abort, exit */ +#define XK_Help 0xff6a /* Help */ +#define XK_Break 0xff6b +#define XK_Mode_switch 0xff7e /* Character set switch */ +#define XK_script_switch 0xff7e /* Alias for mode_switch */ +#define XK_Num_Lock 0xff7f + +/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ + +#define XK_KP_Space 0xff80 /* Space */ +#define XK_KP_Tab 0xff89 +#define XK_KP_Enter 0xff8d /* Enter */ +#define XK_KP_F1 0xff91 /* PF1, KP_A, ... */ +#define XK_KP_F2 0xff92 +#define XK_KP_F3 0xff93 +#define XK_KP_F4 0xff94 +#define XK_KP_Home 0xff95 +#define XK_KP_Left 0xff96 +#define XK_KP_Up 0xff97 +#define XK_KP_Right 0xff98 +#define XK_KP_Down 0xff99 +#define XK_KP_Prior 0xff9a +#define XK_KP_Page_Up 0xff9a +#define XK_KP_Next 0xff9b +#define XK_KP_Page_Down 0xff9b +#define XK_KP_End 0xff9c +#define XK_KP_Begin 0xff9d +#define XK_KP_Insert 0xff9e +#define XK_KP_Delete 0xff9f +#define XK_KP_Equal 0xffbd /* Equals */ +#define XK_KP_Multiply 0xffaa +#define XK_KP_Add 0xffab +#define XK_KP_Separator 0xffac /* Separator, often comma */ +#define XK_KP_Subtract 0xffad +#define XK_KP_Decimal 0xffae +#define XK_KP_Divide 0xffaf + +#define XK_KP_0 0xffb0 +#define XK_KP_1 0xffb1 +#define XK_KP_2 0xffb2 +#define XK_KP_3 0xffb3 +#define XK_KP_4 0xffb4 +#define XK_KP_5 0xffb5 +#define XK_KP_6 0xffb6 +#define XK_KP_7 0xffb7 +#define XK_KP_8 0xffb8 +#define XK_KP_9 0xffb9 + + + +/* + * Auxiliary functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufacturers have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +#define XK_F1 0xffbe +#define XK_F2 0xffbf +#define XK_F3 0xffc0 +#define XK_F4 0xffc1 +#define XK_F5 0xffc2 +#define XK_F6 0xffc3 +#define XK_F7 0xffc4 +#define XK_F8 0xffc5 +#define XK_F9 0xffc6 +#define XK_F10 0xffc7 +#define XK_F11 0xffc8 +#define XK_L1 0xffc8 +#define XK_F12 0xffc9 +#define XK_L2 0xffc9 +#define XK_F13 0xffca +#define XK_L3 0xffca +#define XK_F14 0xffcb +#define XK_L4 0xffcb +#define XK_F15 0xffcc +#define XK_L5 0xffcc +#define XK_F16 0xffcd +#define XK_L6 0xffcd +#define XK_F17 0xffce +#define XK_L7 0xffce +#define XK_F18 0xffcf +#define XK_L8 0xffcf +#define XK_F19 0xffd0 +#define XK_L9 0xffd0 +#define XK_F20 0xffd1 +#define XK_L10 0xffd1 +#define XK_F21 0xffd2 +#define XK_R1 0xffd2 +#define XK_F22 0xffd3 +#define XK_R2 0xffd3 +#define XK_F23 0xffd4 +#define XK_R3 0xffd4 +#define XK_F24 0xffd5 +#define XK_R4 0xffd5 +#define XK_F25 0xffd6 +#define XK_R5 0xffd6 +#define XK_F26 0xffd7 +#define XK_R6 0xffd7 +#define XK_F27 0xffd8 +#define XK_R7 0xffd8 +#define XK_F28 0xffd9 +#define XK_R8 0xffd9 +#define XK_F29 0xffda +#define XK_R9 0xffda +#define XK_F30 0xffdb +#define XK_R10 0xffdb +#define XK_F31 0xffdc +#define XK_R11 0xffdc +#define XK_F32 0xffdd +#define XK_R12 0xffdd +#define XK_F33 0xffde +#define XK_R13 0xffde +#define XK_F34 0xffdf +#define XK_R14 0xffdf +#define XK_F35 0xffe0 +#define XK_R15 0xffe0 + +/* Modifiers */ + +#define XK_Shift_L 0xffe1 /* Left shift */ +#define XK_Shift_R 0xffe2 /* Right shift */ +#define XK_Control_L 0xffe3 /* Left control */ +#define XK_Control_R 0xffe4 /* Right control */ +#define XK_Caps_Lock 0xffe5 /* Caps lock */ +#define XK_Shift_Lock 0xffe6 /* Shift lock */ + +#define XK_Meta_L 0xffe7 /* Left meta */ +#define XK_Meta_R 0xffe8 /* Right meta */ +#define XK_Alt_L 0xffe9 /* Left alt */ +#define XK_Alt_R 0xffea /* Right alt */ +#define XK_Super_L 0xffeb /* Left super */ +#define XK_Super_R 0xffec /* Right super */ +#define XK_Hyper_L 0xffed /* Left hyper */ +#define XK_Hyper_R 0xffee /* Right hyper */ +#endif /* XK_MISCELLANY */ + +/* + * Keyboard (XKB) Extension function and modifier keys + * (from Appendix C of "The X Keyboard Extension: Protocol Specification") + * Byte 3 = 0xfe + */ + +#ifdef XK_XKB_KEYS +#define XK_ISO_Lock 0xfe01 +#define XK_ISO_Level2_Latch 0xfe02 +#define XK_ISO_Level3_Shift 0xfe03 +#define XK_ISO_Level3_Latch 0xfe04 +#define XK_ISO_Level3_Lock 0xfe05 +#define XK_ISO_Level5_Shift 0xfe11 +#define XK_ISO_Level5_Latch 0xfe12 +#define XK_ISO_Level5_Lock 0xfe13 +#define XK_ISO_Group_Shift 0xff7e /* Alias for mode_switch */ +#define XK_ISO_Group_Latch 0xfe06 +#define XK_ISO_Group_Lock 0xfe07 +#define XK_ISO_Next_Group 0xfe08 +#define XK_ISO_Next_Group_Lock 0xfe09 +#define XK_ISO_Prev_Group 0xfe0a +#define XK_ISO_Prev_Group_Lock 0xfe0b +#define XK_ISO_First_Group 0xfe0c +#define XK_ISO_First_Group_Lock 0xfe0d +#define XK_ISO_Last_Group 0xfe0e +#define XK_ISO_Last_Group_Lock 0xfe0f + +#define XK_ISO_Left_Tab 0xfe20 +#define XK_ISO_Move_Line_Up 0xfe21 +#define XK_ISO_Move_Line_Down 0xfe22 +#define XK_ISO_Partial_Line_Up 0xfe23 +#define XK_ISO_Partial_Line_Down 0xfe24 +#define XK_ISO_Partial_Space_Left 0xfe25 +#define XK_ISO_Partial_Space_Right 0xfe26 +#define XK_ISO_Set_Margin_Left 0xfe27 +#define XK_ISO_Set_Margin_Right 0xfe28 +#define XK_ISO_Release_Margin_Left 0xfe29 +#define XK_ISO_Release_Margin_Right 0xfe2a +#define XK_ISO_Release_Both_Margins 0xfe2b +#define XK_ISO_Fast_Cursor_Left 0xfe2c +#define XK_ISO_Fast_Cursor_Right 0xfe2d +#define XK_ISO_Fast_Cursor_Up 0xfe2e +#define XK_ISO_Fast_Cursor_Down 0xfe2f +#define XK_ISO_Continuous_Underline 0xfe30 +#define XK_ISO_Discontinuous_Underline 0xfe31 +#define XK_ISO_Emphasize 0xfe32 +#define XK_ISO_Center_Object 0xfe33 +#define XK_ISO_Enter 0xfe34 + +#define XK_dead_grave 0xfe50 +#define XK_dead_acute 0xfe51 +#define XK_dead_circumflex 0xfe52 +#define XK_dead_tilde 0xfe53 +#define XK_dead_macron 0xfe54 +#define XK_dead_breve 0xfe55 +#define XK_dead_abovedot 0xfe56 +#define XK_dead_diaeresis 0xfe57 +#define XK_dead_abovering 0xfe58 +#define XK_dead_doubleacute 0xfe59 +#define XK_dead_caron 0xfe5a +#define XK_dead_cedilla 0xfe5b +#define XK_dead_ogonek 0xfe5c +#define XK_dead_iota 0xfe5d +#define XK_dead_voiced_sound 0xfe5e +#define XK_dead_semivoiced_sound 0xfe5f +#define XK_dead_belowdot 0xfe60 +#define XK_dead_hook 0xfe61 +#define XK_dead_horn 0xfe62 +#define XK_dead_stroke 0xfe63 +#define XK_dead_abovecomma 0xfe64 +#define XK_dead_psili 0xfe64 /* alias for dead_abovecomma */ +#define XK_dead_abovereversedcomma 0xfe65 +#define XK_dead_dasia 0xfe66 /* alias for dead_abovereversedcomma */ + +#define XK_First_Virtual_Screen 0xfed0 +#define XK_Prev_Virtual_Screen 0xfed1 +#define XK_Next_Virtual_Screen 0xfed2 +#define XK_Last_Virtual_Screen 0xfed4 +#define XK_Terminate_Server 0xfed5 + +#define XK_AccessX_Enable 0xfe70 +#define XK_AccessX_Feedback_Enable 0xfe71 +#define XK_RepeatKeys_Enable 0xfe72 +#define XK_SlowKeys_Enable 0xfe73 +#define XK_BounceKeys_Enable 0xfe74 +#define XK_StickyKeys_Enable 0xfe75 +#define XK_MouseKeys_Enable 0xfe76 +#define XK_MouseKeys_Accel_Enable 0xfe77 +#define XK_Overlay1_Enable 0xfe78 +#define XK_Overlay2_Enable 0xfe79 +#define XK_AudibleBell_Enable 0xfe7a + +#define XK_Pointer_Left 0xfee0 +#define XK_Pointer_Right 0xfee1 +#define XK_Pointer_Up 0xfee2 +#define XK_Pointer_Down 0xfee3 +#define XK_Pointer_UpLeft 0xfee4 +#define XK_Pointer_UpRight 0xfee5 +#define XK_Pointer_DownLeft 0xfee6 +#define XK_Pointer_DownRight 0xfee7 +#define XK_Pointer_Button_Dflt 0xfee8 +#define XK_Pointer_Button1 0xfee9 +#define XK_Pointer_Button2 0xfeea +#define XK_Pointer_Button3 0xfeeb +#define XK_Pointer_Button4 0xfeec +#define XK_Pointer_Button5 0xfeed +#define XK_Pointer_DblClick_Dflt 0xfeee +#define XK_Pointer_DblClick1 0xfeef +#define XK_Pointer_DblClick2 0xfef0 +#define XK_Pointer_DblClick3 0xfef1 +#define XK_Pointer_DblClick4 0xfef2 +#define XK_Pointer_DblClick5 0xfef3 +#define XK_Pointer_Drag_Dflt 0xfef4 +#define XK_Pointer_Drag1 0xfef5 +#define XK_Pointer_Drag2 0xfef6 +#define XK_Pointer_Drag3 0xfef7 +#define XK_Pointer_Drag4 0xfef8 +#define XK_Pointer_Drag5 0xfefd + +#define XK_Pointer_EnableKeys 0xfef9 +#define XK_Pointer_Accelerate 0xfefa +#define XK_Pointer_DfltBtnNext 0xfefb +#define XK_Pointer_DfltBtnPrev 0xfefc + +#endif /* XK_XKB_KEYS */ + +/* + * 3270 Terminal Keys + * Byte 3 = 0xfd + */ + +#ifdef XK_3270 +#define XK_3270_Duplicate 0xfd01 +#define XK_3270_FieldMark 0xfd02 +#define XK_3270_Right2 0xfd03 +#define XK_3270_Left2 0xfd04 +#define XK_3270_BackTab 0xfd05 +#define XK_3270_EraseEOF 0xfd06 +#define XK_3270_EraseInput 0xfd07 +#define XK_3270_Reset 0xfd08 +#define XK_3270_Quit 0xfd09 +#define XK_3270_PA1 0xfd0a +#define XK_3270_PA2 0xfd0b +#define XK_3270_PA3 0xfd0c +#define XK_3270_Test 0xfd0d +#define XK_3270_Attn 0xfd0e +#define XK_3270_CursorBlink 0xfd0f +#define XK_3270_AltCursor 0xfd10 +#define XK_3270_KeyClick 0xfd11 +#define XK_3270_Jump 0xfd12 +#define XK_3270_Ident 0xfd13 +#define XK_3270_Rule 0xfd14 +#define XK_3270_Copy 0xfd15 +#define XK_3270_Play 0xfd16 +#define XK_3270_Setup 0xfd17 +#define XK_3270_Record 0xfd18 +#define XK_3270_ChangeScreen 0xfd19 +#define XK_3270_DeleteWord 0xfd1a +#define XK_3270_ExSelect 0xfd1b +#define XK_3270_CursorSelect 0xfd1c +#define XK_3270_PrintScreen 0xfd1d +#define XK_3270_Enter 0xfd1e +#endif /* XK_3270 */ + +/* + * Latin 1 + * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) + * Byte 3 = 0 + */ +#ifdef XK_LATIN1 +#define XK_space 0x0020 /* U+0020 SPACE */ +#define XK_exclam 0x0021 /* U+0021 EXCLAMATION MARK */ +#define XK_quotedbl 0x0022 /* U+0022 QUOTATION MARK */ +#define XK_numbersign 0x0023 /* U+0023 NUMBER SIGN */ +#define XK_dollar 0x0024 /* U+0024 DOLLAR SIGN */ +#define XK_percent 0x0025 /* U+0025 PERCENT SIGN */ +#define XK_ampersand 0x0026 /* U+0026 AMPERSAND */ +#define XK_apostrophe 0x0027 /* U+0027 APOSTROPHE */ +#define XK_quoteright 0x0027 /* deprecated */ +#define XK_parenleft 0x0028 /* U+0028 LEFT PARENTHESIS */ +#define XK_parenright 0x0029 /* U+0029 RIGHT PARENTHESIS */ +#define XK_asterisk 0x002a /* U+002A ASTERISK */ +#define XK_plus 0x002b /* U+002B PLUS SIGN */ +#define XK_comma 0x002c /* U+002C COMMA */ +#define XK_minus 0x002d /* U+002D HYPHEN-MINUS */ +#define XK_period 0x002e /* U+002E FULL STOP */ +#define XK_slash 0x002f /* U+002F SOLIDUS */ +#define XK_0 0x0030 /* U+0030 DIGIT ZERO */ +#define XK_1 0x0031 /* U+0031 DIGIT ONE */ +#define XK_2 0x0032 /* U+0032 DIGIT TWO */ +#define XK_3 0x0033 /* U+0033 DIGIT THREE */ +#define XK_4 0x0034 /* U+0034 DIGIT FOUR */ +#define XK_5 0x0035 /* U+0035 DIGIT FIVE */ +#define XK_6 0x0036 /* U+0036 DIGIT SIX */ +#define XK_7 0x0037 /* U+0037 DIGIT SEVEN */ +#define XK_8 0x0038 /* U+0038 DIGIT EIGHT */ +#define XK_9 0x0039 /* U+0039 DIGIT NINE */ +#define XK_colon 0x003a /* U+003A COLON */ +#define XK_semicolon 0x003b /* U+003B SEMICOLON */ +#define XK_less 0x003c /* U+003C LESS-THAN SIGN */ +#define XK_equal 0x003d /* U+003D EQUALS SIGN */ +#define XK_greater 0x003e /* U+003E GREATER-THAN SIGN */ +#define XK_question 0x003f /* U+003F QUESTION MARK */ +#define XK_at 0x0040 /* U+0040 COMMERCIAL AT */ +#define XK_A 0x0041 /* U+0041 LATIN CAPITAL LETTER A */ +#define XK_B 0x0042 /* U+0042 LATIN CAPITAL LETTER B */ +#define XK_C 0x0043 /* U+0043 LATIN CAPITAL LETTER C */ +#define XK_D 0x0044 /* U+0044 LATIN CAPITAL LETTER D */ +#define XK_E 0x0045 /* U+0045 LATIN CAPITAL LETTER E */ +#define XK_F 0x0046 /* U+0046 LATIN CAPITAL LETTER F */ +#define XK_G 0x0047 /* U+0047 LATIN CAPITAL LETTER G */ +#define XK_H 0x0048 /* U+0048 LATIN CAPITAL LETTER H */ +#define XK_I 0x0049 /* U+0049 LATIN CAPITAL LETTER I */ +#define XK_J 0x004a /* U+004A LATIN CAPITAL LETTER J */ +#define XK_K 0x004b /* U+004B LATIN CAPITAL LETTER K */ +#define XK_L 0x004c /* U+004C LATIN CAPITAL LETTER L */ +#define XK_M 0x004d /* U+004D LATIN CAPITAL LETTER M */ +#define XK_N 0x004e /* U+004E LATIN CAPITAL LETTER N */ +#define XK_O 0x004f /* U+004F LATIN CAPITAL LETTER O */ +#define XK_P 0x0050 /* U+0050 LATIN CAPITAL LETTER P */ +#define XK_Q 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */ +#define XK_R 0x0052 /* U+0052 LATIN CAPITAL LETTER R */ +#define XK_S 0x0053 /* U+0053 LATIN CAPITAL LETTER S */ +#define XK_T 0x0054 /* U+0054 LATIN CAPITAL LETTER T */ +#define XK_U 0x0055 /* U+0055 LATIN CAPITAL LETTER U */ +#define XK_V 0x0056 /* U+0056 LATIN CAPITAL LETTER V */ +#define XK_W 0x0057 /* U+0057 LATIN CAPITAL LETTER W */ +#define XK_X 0x0058 /* U+0058 LATIN CAPITAL LETTER X */ +#define XK_Y 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */ +#define XK_Z 0x005a /* U+005A LATIN CAPITAL LETTER Z */ +#define XK_bracketleft 0x005b /* U+005B LEFT SQUARE BRACKET */ +#define XK_backslash 0x005c /* U+005C REVERSE SOLIDUS */ +#define XK_bracketright 0x005d /* U+005D RIGHT SQUARE BRACKET */ +#define XK_asciicircum 0x005e /* U+005E CIRCUMFLEX ACCENT */ +#define XK_underscore 0x005f /* U+005F LOW LINE */ +#define XK_grave 0x0060 /* U+0060 GRAVE ACCENT */ +#define XK_quoteleft 0x0060 /* deprecated */ +#define XK_a 0x0061 /* U+0061 LATIN SMALL LETTER A */ +#define XK_b 0x0062 /* U+0062 LATIN SMALL LETTER B */ +#define XK_c 0x0063 /* U+0063 LATIN SMALL LETTER C */ +#define XK_d 0x0064 /* U+0064 LATIN SMALL LETTER D */ +#define XK_e 0x0065 /* U+0065 LATIN SMALL LETTER E */ +#define XK_f 0x0066 /* U+0066 LATIN SMALL LETTER F */ +#define XK_g 0x0067 /* U+0067 LATIN SMALL LETTER G */ +#define XK_h 0x0068 /* U+0068 LATIN SMALL LETTER H */ +#define XK_i 0x0069 /* U+0069 LATIN SMALL LETTER I */ +#define XK_j 0x006a /* U+006A LATIN SMALL LETTER J */ +#define XK_k 0x006b /* U+006B LATIN SMALL LETTER K */ +#define XK_l 0x006c /* U+006C LATIN SMALL LETTER L */ +#define XK_m 0x006d /* U+006D LATIN SMALL LETTER M */ +#define XK_n 0x006e /* U+006E LATIN SMALL LETTER N */ +#define XK_o 0x006f /* U+006F LATIN SMALL LETTER O */ +#define XK_p 0x0070 /* U+0070 LATIN SMALL LETTER P */ +#define XK_q 0x0071 /* U+0071 LATIN SMALL LETTER Q */ +#define XK_r 0x0072 /* U+0072 LATIN SMALL LETTER R */ +#define XK_s 0x0073 /* U+0073 LATIN SMALL LETTER S */ +#define XK_t 0x0074 /* U+0074 LATIN SMALL LETTER T */ +#define XK_u 0x0075 /* U+0075 LATIN SMALL LETTER U */ +#define XK_v 0x0076 /* U+0076 LATIN SMALL LETTER V */ +#define XK_w 0x0077 /* U+0077 LATIN SMALL LETTER W */ +#define XK_x 0x0078 /* U+0078 LATIN SMALL LETTER X */ +#define XK_y 0x0079 /* U+0079 LATIN SMALL LETTER Y */ +#define XK_z 0x007a /* U+007A LATIN SMALL LETTER Z */ +#define XK_braceleft 0x007b /* U+007B LEFT CURLY BRACKET */ +#define XK_bar 0x007c /* U+007C VERTICAL LINE */ +#define XK_braceright 0x007d /* U+007D RIGHT CURLY BRACKET */ +#define XK_asciitilde 0x007e /* U+007E TILDE */ + +#define XK_nobreakspace 0x00a0 /* U+00A0 NO-BREAK SPACE */ +#define XK_exclamdown 0x00a1 /* U+00A1 INVERTED EXCLAMATION MARK */ +#define XK_cent 0x00a2 /* U+00A2 CENT SIGN */ +#define XK_sterling 0x00a3 /* U+00A3 POUND SIGN */ +#define XK_currency 0x00a4 /* U+00A4 CURRENCY SIGN */ +#define XK_yen 0x00a5 /* U+00A5 YEN SIGN */ +#define XK_brokenbar 0x00a6 /* U+00A6 BROKEN BAR */ +#define XK_section 0x00a7 /* U+00A7 SECTION SIGN */ +#define XK_diaeresis 0x00a8 /* U+00A8 DIAERESIS */ +#define XK_copyright 0x00a9 /* U+00A9 COPYRIGHT SIGN */ +#define XK_ordfeminine 0x00aa /* U+00AA FEMININE ORDINAL INDICATOR */ +#define XK_guillemotleft 0x00ab /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ +#define XK_notsign 0x00ac /* U+00AC NOT SIGN */ +#define XK_hyphen 0x00ad /* U+00AD SOFT HYPHEN */ +#define XK_registered 0x00ae /* U+00AE REGISTERED SIGN */ +#define XK_macron 0x00af /* U+00AF MACRON */ +#define XK_degree 0x00b0 /* U+00B0 DEGREE SIGN */ +#define XK_plusminus 0x00b1 /* U+00B1 PLUS-MINUS SIGN */ +#define XK_twosuperior 0x00b2 /* U+00B2 SUPERSCRIPT TWO */ +#define XK_threesuperior 0x00b3 /* U+00B3 SUPERSCRIPT THREE */ +#define XK_acute 0x00b4 /* U+00B4 ACUTE ACCENT */ +#define XK_mu 0x00b5 /* U+00B5 MICRO SIGN */ +#define XK_paragraph 0x00b6 /* U+00B6 PILCROW SIGN */ +#define XK_periodcentered 0x00b7 /* U+00B7 MIDDLE DOT */ +#define XK_cedilla 0x00b8 /* U+00B8 CEDILLA */ +#define XK_onesuperior 0x00b9 /* U+00B9 SUPERSCRIPT ONE */ +#define XK_masculine 0x00ba /* U+00BA MASCULINE ORDINAL INDICATOR */ +#define XK_guillemotright 0x00bb /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ +#define XK_onequarter 0x00bc /* U+00BC VULGAR FRACTION ONE QUARTER */ +#define XK_onehalf 0x00bd /* U+00BD VULGAR FRACTION ONE HALF */ +#define XK_threequarters 0x00be /* U+00BE VULGAR FRACTION THREE QUARTERS */ +#define XK_questiondown 0x00bf /* U+00BF INVERTED QUESTION MARK */ +#define XK_Agrave 0x00c0 /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ +#define XK_Aacute 0x00c1 /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ +#define XK_Acircumflex 0x00c2 /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ +#define XK_Atilde 0x00c3 /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ +#define XK_Adiaeresis 0x00c4 /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ +#define XK_Aring 0x00c5 /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ +#define XK_AE 0x00c6 /* U+00C6 LATIN CAPITAL LETTER AE */ +#define XK_Ccedilla 0x00c7 /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ +#define XK_Egrave 0x00c8 /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ +#define XK_Eacute 0x00c9 /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ +#define XK_Ecircumflex 0x00ca /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ +#define XK_Ediaeresis 0x00cb /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ +#define XK_Igrave 0x00cc /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ +#define XK_Iacute 0x00cd /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ +#define XK_Icircumflex 0x00ce /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ +#define XK_Idiaeresis 0x00cf /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ +#define XK_ETH 0x00d0 /* U+00D0 LATIN CAPITAL LETTER ETH */ +#define XK_Eth 0x00d0 /* deprecated */ +#define XK_Ntilde 0x00d1 /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ +#define XK_Ograve 0x00d2 /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ +#define XK_Oacute 0x00d3 /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ +#define XK_Ocircumflex 0x00d4 /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ +#define XK_Otilde 0x00d5 /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ +#define XK_Odiaeresis 0x00d6 /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ +#define XK_multiply 0x00d7 /* U+00D7 MULTIPLICATION SIGN */ +#define XK_Oslash 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ +#define XK_Ooblique 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ +#define XK_Ugrave 0x00d9 /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ +#define XK_Uacute 0x00da /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ +#define XK_Ucircumflex 0x00db /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ +#define XK_Udiaeresis 0x00dc /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ +#define XK_Yacute 0x00dd /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ +#define XK_THORN 0x00de /* U+00DE LATIN CAPITAL LETTER THORN */ +#define XK_Thorn 0x00de /* deprecated */ +#define XK_ssharp 0x00df /* U+00DF LATIN SMALL LETTER SHARP S */ +#define XK_agrave 0x00e0 /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ +#define XK_aacute 0x00e1 /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ +#define XK_acircumflex 0x00e2 /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ +#define XK_atilde 0x00e3 /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ +#define XK_adiaeresis 0x00e4 /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ +#define XK_aring 0x00e5 /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ +#define XK_ae 0x00e6 /* U+00E6 LATIN SMALL LETTER AE */ +#define XK_ccedilla 0x00e7 /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ +#define XK_egrave 0x00e8 /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ +#define XK_eacute 0x00e9 /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ +#define XK_ecircumflex 0x00ea /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ +#define XK_ediaeresis 0x00eb /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ +#define XK_igrave 0x00ec /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ +#define XK_iacute 0x00ed /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ +#define XK_icircumflex 0x00ee /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ +#define XK_idiaeresis 0x00ef /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ +#define XK_eth 0x00f0 /* U+00F0 LATIN SMALL LETTER ETH */ +#define XK_ntilde 0x00f1 /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ +#define XK_ograve 0x00f2 /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ +#define XK_oacute 0x00f3 /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ +#define XK_ocircumflex 0x00f4 /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ +#define XK_otilde 0x00f5 /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ +#define XK_odiaeresis 0x00f6 /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ +#define XK_division 0x00f7 /* U+00F7 DIVISION SIGN */ +#define XK_oslash 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ +#define XK_ooblique 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ +#define XK_ugrave 0x00f9 /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ +#define XK_uacute 0x00fa /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ +#define XK_ucircumflex 0x00fb /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ +#define XK_udiaeresis 0x00fc /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ +#define XK_yacute 0x00fd /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ +#define XK_thorn 0x00fe /* U+00FE LATIN SMALL LETTER THORN */ +#define XK_ydiaeresis 0x00ff /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ +#endif /* XK_LATIN1 */ + +/* + * Latin 2 + * Byte 3 = 1 + */ + +#ifdef XK_LATIN2 +#define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */ +#define XK_breve 0x01a2 /* U+02D8 BREVE */ +#define XK_Lstroke 0x01a3 /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */ +#define XK_Lcaron 0x01a5 /* U+013D LATIN CAPITAL LETTER L WITH CARON */ +#define XK_Sacute 0x01a6 /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */ +#define XK_Scaron 0x01a9 /* U+0160 LATIN CAPITAL LETTER S WITH CARON */ +#define XK_Scedilla 0x01aa /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */ +#define XK_Tcaron 0x01ab /* U+0164 LATIN CAPITAL LETTER T WITH CARON */ +#define XK_Zacute 0x01ac /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */ +#define XK_Zcaron 0x01ae /* U+017D LATIN CAPITAL LETTER Z WITH CARON */ +#define XK_Zabovedot 0x01af /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */ +#define XK_aogonek 0x01b1 /* U+0105 LATIN SMALL LETTER A WITH OGONEK */ +#define XK_ogonek 0x01b2 /* U+02DB OGONEK */ +#define XK_lstroke 0x01b3 /* U+0142 LATIN SMALL LETTER L WITH STROKE */ +#define XK_lcaron 0x01b5 /* U+013E LATIN SMALL LETTER L WITH CARON */ +#define XK_sacute 0x01b6 /* U+015B LATIN SMALL LETTER S WITH ACUTE */ +#define XK_caron 0x01b7 /* U+02C7 CARON */ +#define XK_scaron 0x01b9 /* U+0161 LATIN SMALL LETTER S WITH CARON */ +#define XK_scedilla 0x01ba /* U+015F LATIN SMALL LETTER S WITH CEDILLA */ +#define XK_tcaron 0x01bb /* U+0165 LATIN SMALL LETTER T WITH CARON */ +#define XK_zacute 0x01bc /* U+017A LATIN SMALL LETTER Z WITH ACUTE */ +#define XK_doubleacute 0x01bd /* U+02DD DOUBLE ACUTE ACCENT */ +#define XK_zcaron 0x01be /* U+017E LATIN SMALL LETTER Z WITH CARON */ +#define XK_zabovedot 0x01bf /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */ +#define XK_Racute 0x01c0 /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */ +#define XK_Abreve 0x01c3 /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */ +#define XK_Lacute 0x01c5 /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */ +#define XK_Cacute 0x01c6 /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */ +#define XK_Ccaron 0x01c8 /* U+010C LATIN CAPITAL LETTER C WITH CARON */ +#define XK_Eogonek 0x01ca /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */ +#define XK_Ecaron 0x01cc /* U+011A LATIN CAPITAL LETTER E WITH CARON */ +#define XK_Dcaron 0x01cf /* U+010E LATIN CAPITAL LETTER D WITH CARON */ +#define XK_Dstroke 0x01d0 /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */ +#define XK_Nacute 0x01d1 /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */ +#define XK_Ncaron 0x01d2 /* U+0147 LATIN CAPITAL LETTER N WITH CARON */ +#define XK_Odoubleacute 0x01d5 /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ +#define XK_Rcaron 0x01d8 /* U+0158 LATIN CAPITAL LETTER R WITH CARON */ +#define XK_Uring 0x01d9 /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */ +#define XK_Udoubleacute 0x01db /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ +#define XK_Tcedilla 0x01de /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */ +#define XK_racute 0x01e0 /* U+0155 LATIN SMALL LETTER R WITH ACUTE */ +#define XK_abreve 0x01e3 /* U+0103 LATIN SMALL LETTER A WITH BREVE */ +#define XK_lacute 0x01e5 /* U+013A LATIN SMALL LETTER L WITH ACUTE */ +#define XK_cacute 0x01e6 /* U+0107 LATIN SMALL LETTER C WITH ACUTE */ +#define XK_ccaron 0x01e8 /* U+010D LATIN SMALL LETTER C WITH CARON */ +#define XK_eogonek 0x01ea /* U+0119 LATIN SMALL LETTER E WITH OGONEK */ +#define XK_ecaron 0x01ec /* U+011B LATIN SMALL LETTER E WITH CARON */ +#define XK_dcaron 0x01ef /* U+010F LATIN SMALL LETTER D WITH CARON */ +#define XK_dstroke 0x01f0 /* U+0111 LATIN SMALL LETTER D WITH STROKE */ +#define XK_nacute 0x01f1 /* U+0144 LATIN SMALL LETTER N WITH ACUTE */ +#define XK_ncaron 0x01f2 /* U+0148 LATIN SMALL LETTER N WITH CARON */ +#define XK_odoubleacute 0x01f5 /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */ +#define XK_udoubleacute 0x01fb /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */ +#define XK_rcaron 0x01f8 /* U+0159 LATIN SMALL LETTER R WITH CARON */ +#define XK_uring 0x01f9 /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */ +#define XK_tcedilla 0x01fe /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */ +#define XK_abovedot 0x01ff /* U+02D9 DOT ABOVE */ +#endif /* XK_LATIN2 */ + +/* + * Latin 3 + * Byte 3 = 2 + */ + +#ifdef XK_LATIN3 +#define XK_Hstroke 0x02a1 /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */ +#define XK_Hcircumflex 0x02a6 /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ +#define XK_Iabovedot 0x02a9 /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */ +#define XK_Gbreve 0x02ab /* U+011E LATIN CAPITAL LETTER G WITH BREVE */ +#define XK_Jcircumflex 0x02ac /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ +#define XK_hstroke 0x02b1 /* U+0127 LATIN SMALL LETTER H WITH STROKE */ +#define XK_hcircumflex 0x02b6 /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */ +#define XK_idotless 0x02b9 /* U+0131 LATIN SMALL LETTER DOTLESS I */ +#define XK_gbreve 0x02bb /* U+011F LATIN SMALL LETTER G WITH BREVE */ +#define XK_jcircumflex 0x02bc /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */ +#define XK_Cabovedot 0x02c5 /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */ +#define XK_Ccircumflex 0x02c6 /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ +#define XK_Gabovedot 0x02d5 /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */ +#define XK_Gcircumflex 0x02d8 /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ +#define XK_Ubreve 0x02dd /* U+016C LATIN CAPITAL LETTER U WITH BREVE */ +#define XK_Scircumflex 0x02de /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ +#define XK_cabovedot 0x02e5 /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */ +#define XK_ccircumflex 0x02e6 /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */ +#define XK_gabovedot 0x02f5 /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */ +#define XK_gcircumflex 0x02f8 /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */ +#define XK_ubreve 0x02fd /* U+016D LATIN SMALL LETTER U WITH BREVE */ +#define XK_scircumflex 0x02fe /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */ +#endif /* XK_LATIN3 */ + + +/* + * Latin 4 + * Byte 3 = 3 + */ + +#ifdef XK_LATIN4 +#define XK_kra 0x03a2 /* U+0138 LATIN SMALL LETTER KRA */ +#define XK_kappa 0x03a2 /* deprecated */ +#define XK_Rcedilla 0x03a3 /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */ +#define XK_Itilde 0x03a5 /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */ +#define XK_Lcedilla 0x03a6 /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */ +#define XK_Emacron 0x03aa /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */ +#define XK_Gcedilla 0x03ab /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */ +#define XK_Tslash 0x03ac /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */ +#define XK_rcedilla 0x03b3 /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */ +#define XK_itilde 0x03b5 /* U+0129 LATIN SMALL LETTER I WITH TILDE */ +#define XK_lcedilla 0x03b6 /* U+013C LATIN SMALL LETTER L WITH CEDILLA */ +#define XK_emacron 0x03ba /* U+0113 LATIN SMALL LETTER E WITH MACRON */ +#define XK_gcedilla 0x03bb /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */ +#define XK_tslash 0x03bc /* U+0167 LATIN SMALL LETTER T WITH STROKE */ +#define XK_ENG 0x03bd /* U+014A LATIN CAPITAL LETTER ENG */ +#define XK_eng 0x03bf /* U+014B LATIN SMALL LETTER ENG */ +#define XK_Amacron 0x03c0 /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */ +#define XK_Iogonek 0x03c7 /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */ +#define XK_Eabovedot 0x03cc /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */ +#define XK_Imacron 0x03cf /* U+012A LATIN CAPITAL LETTER I WITH MACRON */ +#define XK_Ncedilla 0x03d1 /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */ +#define XK_Omacron 0x03d2 /* U+014C LATIN CAPITAL LETTER O WITH MACRON */ +#define XK_Kcedilla 0x03d3 /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */ +#define XK_Uogonek 0x03d9 /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */ +#define XK_Utilde 0x03dd /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */ +#define XK_Umacron 0x03de /* U+016A LATIN CAPITAL LETTER U WITH MACRON */ +#define XK_amacron 0x03e0 /* U+0101 LATIN SMALL LETTER A WITH MACRON */ +#define XK_iogonek 0x03e7 /* U+012F LATIN SMALL LETTER I WITH OGONEK */ +#define XK_eabovedot 0x03ec /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */ +#define XK_imacron 0x03ef /* U+012B LATIN SMALL LETTER I WITH MACRON */ +#define XK_ncedilla 0x03f1 /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */ +#define XK_omacron 0x03f2 /* U+014D LATIN SMALL LETTER O WITH MACRON */ +#define XK_kcedilla 0x03f3 /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */ +#define XK_uogonek 0x03f9 /* U+0173 LATIN SMALL LETTER U WITH OGONEK */ +#define XK_utilde 0x03fd /* U+0169 LATIN SMALL LETTER U WITH TILDE */ +#define XK_umacron 0x03fe /* U+016B LATIN SMALL LETTER U WITH MACRON */ +#endif /* XK_LATIN4 */ + +/* + * Latin 8 + */ +#ifdef XK_LATIN8 +#define XK_Babovedot 0x1001e02 /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */ +#define XK_babovedot 0x1001e03 /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */ +#define XK_Dabovedot 0x1001e0a /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */ +#define XK_Wgrave 0x1001e80 /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */ +#define XK_Wacute 0x1001e82 /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */ +#define XK_dabovedot 0x1001e0b /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */ +#define XK_Ygrave 0x1001ef2 /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */ +#define XK_Fabovedot 0x1001e1e /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */ +#define XK_fabovedot 0x1001e1f /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */ +#define XK_Mabovedot 0x1001e40 /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */ +#define XK_mabovedot 0x1001e41 /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */ +#define XK_Pabovedot 0x1001e56 /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */ +#define XK_wgrave 0x1001e81 /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */ +#define XK_pabovedot 0x1001e57 /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */ +#define XK_wacute 0x1001e83 /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */ +#define XK_Sabovedot 0x1001e60 /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */ +#define XK_ygrave 0x1001ef3 /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */ +#define XK_Wdiaeresis 0x1001e84 /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */ +#define XK_wdiaeresis 0x1001e85 /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */ +#define XK_sabovedot 0x1001e61 /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */ +#define XK_Wcircumflex 0x1000174 /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ +#define XK_Tabovedot 0x1001e6a /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */ +#define XK_Ycircumflex 0x1000176 /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ +#define XK_wcircumflex 0x1000175 /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */ +#define XK_tabovedot 0x1001e6b /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */ +#define XK_ycircumflex 0x1000177 /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */ +#endif /* XK_LATIN8 */ + +/* + * Latin 9 + * Byte 3 = 0x13 + */ + +#ifdef XK_LATIN9 +#define XK_OE 0x13bc /* U+0152 LATIN CAPITAL LIGATURE OE */ +#define XK_oe 0x13bd /* U+0153 LATIN SMALL LIGATURE OE */ +#define XK_Ydiaeresis 0x13be /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */ +#endif /* XK_LATIN9 */ + +/* + * Katakana + * Byte 3 = 4 + */ + +#ifdef XK_KATAKANA +#define XK_overline 0x047e /* U+203E OVERLINE */ +#define XK_kana_fullstop 0x04a1 /* U+3002 IDEOGRAPHIC FULL STOP */ +#define XK_kana_openingbracket 0x04a2 /* U+300C LEFT CORNER BRACKET */ +#define XK_kana_closingbracket 0x04a3 /* U+300D RIGHT CORNER BRACKET */ +#define XK_kana_comma 0x04a4 /* U+3001 IDEOGRAPHIC COMMA */ +#define XK_kana_conjunctive 0x04a5 /* U+30FB KATAKANA MIDDLE DOT */ +#define XK_kana_middledot 0x04a5 /* deprecated */ +#define XK_kana_WO 0x04a6 /* U+30F2 KATAKANA LETTER WO */ +#define XK_kana_a 0x04a7 /* U+30A1 KATAKANA LETTER SMALL A */ +#define XK_kana_i 0x04a8 /* U+30A3 KATAKANA LETTER SMALL I */ +#define XK_kana_u 0x04a9 /* U+30A5 KATAKANA LETTER SMALL U */ +#define XK_kana_e 0x04aa /* U+30A7 KATAKANA LETTER SMALL E */ +#define XK_kana_o 0x04ab /* U+30A9 KATAKANA LETTER SMALL O */ +#define XK_kana_ya 0x04ac /* U+30E3 KATAKANA LETTER SMALL YA */ +#define XK_kana_yu 0x04ad /* U+30E5 KATAKANA LETTER SMALL YU */ +#define XK_kana_yo 0x04ae /* U+30E7 KATAKANA LETTER SMALL YO */ +#define XK_kana_tsu 0x04af /* U+30C3 KATAKANA LETTER SMALL TU */ +#define XK_kana_tu 0x04af /* deprecated */ +#define XK_prolongedsound 0x04b0 /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */ +#define XK_kana_A 0x04b1 /* U+30A2 KATAKANA LETTER A */ +#define XK_kana_I 0x04b2 /* U+30A4 KATAKANA LETTER I */ +#define XK_kana_U 0x04b3 /* U+30A6 KATAKANA LETTER U */ +#define XK_kana_E 0x04b4 /* U+30A8 KATAKANA LETTER E */ +#define XK_kana_O 0x04b5 /* U+30AA KATAKANA LETTER O */ +#define XK_kana_KA 0x04b6 /* U+30AB KATAKANA LETTER KA */ +#define XK_kana_KI 0x04b7 /* U+30AD KATAKANA LETTER KI */ +#define XK_kana_KU 0x04b8 /* U+30AF KATAKANA LETTER KU */ +#define XK_kana_KE 0x04b9 /* U+30B1 KATAKANA LETTER KE */ +#define XK_kana_KO 0x04ba /* U+30B3 KATAKANA LETTER KO */ +#define XK_kana_SA 0x04bb /* U+30B5 KATAKANA LETTER SA */ +#define XK_kana_SHI 0x04bc /* U+30B7 KATAKANA LETTER SI */ +#define XK_kana_SU 0x04bd /* U+30B9 KATAKANA LETTER SU */ +#define XK_kana_SE 0x04be /* U+30BB KATAKANA LETTER SE */ +#define XK_kana_SO 0x04bf /* U+30BD KATAKANA LETTER SO */ +#define XK_kana_TA 0x04c0 /* U+30BF KATAKANA LETTER TA */ +#define XK_kana_CHI 0x04c1 /* U+30C1 KATAKANA LETTER TI */ +#define XK_kana_TI 0x04c1 /* deprecated */ +#define XK_kana_TSU 0x04c2 /* U+30C4 KATAKANA LETTER TU */ +#define XK_kana_TU 0x04c2 /* deprecated */ +#define XK_kana_TE 0x04c3 /* U+30C6 KATAKANA LETTER TE */ +#define XK_kana_TO 0x04c4 /* U+30C8 KATAKANA LETTER TO */ +#define XK_kana_NA 0x04c5 /* U+30CA KATAKANA LETTER NA */ +#define XK_kana_NI 0x04c6 /* U+30CB KATAKANA LETTER NI */ +#define XK_kana_NU 0x04c7 /* U+30CC KATAKANA LETTER NU */ +#define XK_kana_NE 0x04c8 /* U+30CD KATAKANA LETTER NE */ +#define XK_kana_NO 0x04c9 /* U+30CE KATAKANA LETTER NO */ +#define XK_kana_HA 0x04ca /* U+30CF KATAKANA LETTER HA */ +#define XK_kana_HI 0x04cb /* U+30D2 KATAKANA LETTER HI */ +#define XK_kana_FU 0x04cc /* U+30D5 KATAKANA LETTER HU */ +#define XK_kana_HU 0x04cc /* deprecated */ +#define XK_kana_HE 0x04cd /* U+30D8 KATAKANA LETTER HE */ +#define XK_kana_HO 0x04ce /* U+30DB KATAKANA LETTER HO */ +#define XK_kana_MA 0x04cf /* U+30DE KATAKANA LETTER MA */ +#define XK_kana_MI 0x04d0 /* U+30DF KATAKANA LETTER MI */ +#define XK_kana_MU 0x04d1 /* U+30E0 KATAKANA LETTER MU */ +#define XK_kana_ME 0x04d2 /* U+30E1 KATAKANA LETTER ME */ +#define XK_kana_MO 0x04d3 /* U+30E2 KATAKANA LETTER MO */ +#define XK_kana_YA 0x04d4 /* U+30E4 KATAKANA LETTER YA */ +#define XK_kana_YU 0x04d5 /* U+30E6 KATAKANA LETTER YU */ +#define XK_kana_YO 0x04d6 /* U+30E8 KATAKANA LETTER YO */ +#define XK_kana_RA 0x04d7 /* U+30E9 KATAKANA LETTER RA */ +#define XK_kana_RI 0x04d8 /* U+30EA KATAKANA LETTER RI */ +#define XK_kana_RU 0x04d9 /* U+30EB KATAKANA LETTER RU */ +#define XK_kana_RE 0x04da /* U+30EC KATAKANA LETTER RE */ +#define XK_kana_RO 0x04db /* U+30ED KATAKANA LETTER RO */ +#define XK_kana_WA 0x04dc /* U+30EF KATAKANA LETTER WA */ +#define XK_kana_N 0x04dd /* U+30F3 KATAKANA LETTER N */ +#define XK_voicedsound 0x04de /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */ +#define XK_semivoicedsound 0x04df /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ +#define XK_kana_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_KATAKANA */ + +/* + * Arabic + * Byte 3 = 5 + */ + +#ifdef XK_ARABIC +#define XK_Farsi_0 0x10006f0 /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */ +#define XK_Farsi_1 0x10006f1 /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */ +#define XK_Farsi_2 0x10006f2 /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */ +#define XK_Farsi_3 0x10006f3 /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */ +#define XK_Farsi_4 0x10006f4 /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */ +#define XK_Farsi_5 0x10006f5 /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */ +#define XK_Farsi_6 0x10006f6 /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */ +#define XK_Farsi_7 0x10006f7 /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */ +#define XK_Farsi_8 0x10006f8 /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */ +#define XK_Farsi_9 0x10006f9 /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */ +#define XK_Arabic_percent 0x100066a /* U+066A ARABIC PERCENT SIGN */ +#define XK_Arabic_superscript_alef 0x1000670 /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */ +#define XK_Arabic_tteh 0x1000679 /* U+0679 ARABIC LETTER TTEH */ +#define XK_Arabic_peh 0x100067e /* U+067E ARABIC LETTER PEH */ +#define XK_Arabic_tcheh 0x1000686 /* U+0686 ARABIC LETTER TCHEH */ +#define XK_Arabic_ddal 0x1000688 /* U+0688 ARABIC LETTER DDAL */ +#define XK_Arabic_rreh 0x1000691 /* U+0691 ARABIC LETTER RREH */ +#define XK_Arabic_comma 0x05ac /* U+060C ARABIC COMMA */ +#define XK_Arabic_fullstop 0x10006d4 /* U+06D4 ARABIC FULL STOP */ +#define XK_Arabic_0 0x1000660 /* U+0660 ARABIC-INDIC DIGIT ZERO */ +#define XK_Arabic_1 0x1000661 /* U+0661 ARABIC-INDIC DIGIT ONE */ +#define XK_Arabic_2 0x1000662 /* U+0662 ARABIC-INDIC DIGIT TWO */ +#define XK_Arabic_3 0x1000663 /* U+0663 ARABIC-INDIC DIGIT THREE */ +#define XK_Arabic_4 0x1000664 /* U+0664 ARABIC-INDIC DIGIT FOUR */ +#define XK_Arabic_5 0x1000665 /* U+0665 ARABIC-INDIC DIGIT FIVE */ +#define XK_Arabic_6 0x1000666 /* U+0666 ARABIC-INDIC DIGIT SIX */ +#define XK_Arabic_7 0x1000667 /* U+0667 ARABIC-INDIC DIGIT SEVEN */ +#define XK_Arabic_8 0x1000668 /* U+0668 ARABIC-INDIC DIGIT EIGHT */ +#define XK_Arabic_9 0x1000669 /* U+0669 ARABIC-INDIC DIGIT NINE */ +#define XK_Arabic_semicolon 0x05bb /* U+061B ARABIC SEMICOLON */ +#define XK_Arabic_question_mark 0x05bf /* U+061F ARABIC QUESTION MARK */ +#define XK_Arabic_hamza 0x05c1 /* U+0621 ARABIC LETTER HAMZA */ +#define XK_Arabic_maddaonalef 0x05c2 /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */ +#define XK_Arabic_hamzaonalef 0x05c3 /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */ +#define XK_Arabic_hamzaonwaw 0x05c4 /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */ +#define XK_Arabic_hamzaunderalef 0x05c5 /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */ +#define XK_Arabic_hamzaonyeh 0x05c6 /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */ +#define XK_Arabic_alef 0x05c7 /* U+0627 ARABIC LETTER ALEF */ +#define XK_Arabic_beh 0x05c8 /* U+0628 ARABIC LETTER BEH */ +#define XK_Arabic_tehmarbuta 0x05c9 /* U+0629 ARABIC LETTER TEH MARBUTA */ +#define XK_Arabic_teh 0x05ca /* U+062A ARABIC LETTER TEH */ +#define XK_Arabic_theh 0x05cb /* U+062B ARABIC LETTER THEH */ +#define XK_Arabic_jeem 0x05cc /* U+062C ARABIC LETTER JEEM */ +#define XK_Arabic_hah 0x05cd /* U+062D ARABIC LETTER HAH */ +#define XK_Arabic_khah 0x05ce /* U+062E ARABIC LETTER KHAH */ +#define XK_Arabic_dal 0x05cf /* U+062F ARABIC LETTER DAL */ +#define XK_Arabic_thal 0x05d0 /* U+0630 ARABIC LETTER THAL */ +#define XK_Arabic_ra 0x05d1 /* U+0631 ARABIC LETTER REH */ +#define XK_Arabic_zain 0x05d2 /* U+0632 ARABIC LETTER ZAIN */ +#define XK_Arabic_seen 0x05d3 /* U+0633 ARABIC LETTER SEEN */ +#define XK_Arabic_sheen 0x05d4 /* U+0634 ARABIC LETTER SHEEN */ +#define XK_Arabic_sad 0x05d5 /* U+0635 ARABIC LETTER SAD */ +#define XK_Arabic_dad 0x05d6 /* U+0636 ARABIC LETTER DAD */ +#define XK_Arabic_tah 0x05d7 /* U+0637 ARABIC LETTER TAH */ +#define XK_Arabic_zah 0x05d8 /* U+0638 ARABIC LETTER ZAH */ +#define XK_Arabic_ain 0x05d9 /* U+0639 ARABIC LETTER AIN */ +#define XK_Arabic_ghain 0x05da /* U+063A ARABIC LETTER GHAIN */ +#define XK_Arabic_tatweel 0x05e0 /* U+0640 ARABIC TATWEEL */ +#define XK_Arabic_feh 0x05e1 /* U+0641 ARABIC LETTER FEH */ +#define XK_Arabic_qaf 0x05e2 /* U+0642 ARABIC LETTER QAF */ +#define XK_Arabic_kaf 0x05e3 /* U+0643 ARABIC LETTER KAF */ +#define XK_Arabic_lam 0x05e4 /* U+0644 ARABIC LETTER LAM */ +#define XK_Arabic_meem 0x05e5 /* U+0645 ARABIC LETTER MEEM */ +#define XK_Arabic_noon 0x05e6 /* U+0646 ARABIC LETTER NOON */ +#define XK_Arabic_ha 0x05e7 /* U+0647 ARABIC LETTER HEH */ +#define XK_Arabic_heh 0x05e7 /* deprecated */ +#define XK_Arabic_waw 0x05e8 /* U+0648 ARABIC LETTER WAW */ +#define XK_Arabic_alefmaksura 0x05e9 /* U+0649 ARABIC LETTER ALEF MAKSURA */ +#define XK_Arabic_yeh 0x05ea /* U+064A ARABIC LETTER YEH */ +#define XK_Arabic_fathatan 0x05eb /* U+064B ARABIC FATHATAN */ +#define XK_Arabic_dammatan 0x05ec /* U+064C ARABIC DAMMATAN */ +#define XK_Arabic_kasratan 0x05ed /* U+064D ARABIC KASRATAN */ +#define XK_Arabic_fatha 0x05ee /* U+064E ARABIC FATHA */ +#define XK_Arabic_damma 0x05ef /* U+064F ARABIC DAMMA */ +#define XK_Arabic_kasra 0x05f0 /* U+0650 ARABIC KASRA */ +#define XK_Arabic_shadda 0x05f1 /* U+0651 ARABIC SHADDA */ +#define XK_Arabic_sukun 0x05f2 /* U+0652 ARABIC SUKUN */ +#define XK_Arabic_madda_above 0x1000653 /* U+0653 ARABIC MADDAH ABOVE */ +#define XK_Arabic_hamza_above 0x1000654 /* U+0654 ARABIC HAMZA ABOVE */ +#define XK_Arabic_hamza_below 0x1000655 /* U+0655 ARABIC HAMZA BELOW */ +#define XK_Arabic_jeh 0x1000698 /* U+0698 ARABIC LETTER JEH */ +#define XK_Arabic_veh 0x10006a4 /* U+06A4 ARABIC LETTER VEH */ +#define XK_Arabic_keheh 0x10006a9 /* U+06A9 ARABIC LETTER KEHEH */ +#define XK_Arabic_gaf 0x10006af /* U+06AF ARABIC LETTER GAF */ +#define XK_Arabic_noon_ghunna 0x10006ba /* U+06BA ARABIC LETTER NOON GHUNNA */ +#define XK_Arabic_heh_doachashmee 0x10006be /* U+06BE ARABIC LETTER HEH DOACHASHMEE */ +#define XK_Farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ +#define XK_Arabic_farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ +#define XK_Arabic_yeh_baree 0x10006d2 /* U+06D2 ARABIC LETTER YEH BARREE */ +#define XK_Arabic_heh_goal 0x10006c1 /* U+06C1 ARABIC LETTER HEH GOAL */ +#define XK_Arabic_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_ARABIC */ + +/* + * Cyrillic + * Byte 3 = 6 + */ +#ifdef XK_CYRILLIC +#define XK_Cyrillic_GHE_bar 0x1000492 /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */ +#define XK_Cyrillic_ghe_bar 0x1000493 /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */ +#define XK_Cyrillic_ZHE_descender 0x1000496 /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */ +#define XK_Cyrillic_zhe_descender 0x1000497 /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */ +#define XK_Cyrillic_KA_descender 0x100049a /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */ +#define XK_Cyrillic_ka_descender 0x100049b /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */ +#define XK_Cyrillic_KA_vertstroke 0x100049c /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */ +#define XK_Cyrillic_ka_vertstroke 0x100049d /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */ +#define XK_Cyrillic_EN_descender 0x10004a2 /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */ +#define XK_Cyrillic_en_descender 0x10004a3 /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */ +#define XK_Cyrillic_U_straight 0x10004ae /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */ +#define XK_Cyrillic_u_straight 0x10004af /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */ +#define XK_Cyrillic_U_straight_bar 0x10004b0 /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */ +#define XK_Cyrillic_u_straight_bar 0x10004b1 /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */ +#define XK_Cyrillic_HA_descender 0x10004b2 /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */ +#define XK_Cyrillic_ha_descender 0x10004b3 /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */ +#define XK_Cyrillic_CHE_descender 0x10004b6 /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */ +#define XK_Cyrillic_che_descender 0x10004b7 /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */ +#define XK_Cyrillic_CHE_vertstroke 0x10004b8 /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */ +#define XK_Cyrillic_che_vertstroke 0x10004b9 /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */ +#define XK_Cyrillic_SHHA 0x10004ba /* U+04BA CYRILLIC CAPITAL LETTER SHHA */ +#define XK_Cyrillic_shha 0x10004bb /* U+04BB CYRILLIC SMALL LETTER SHHA */ + +#define XK_Cyrillic_SCHWA 0x10004d8 /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */ +#define XK_Cyrillic_schwa 0x10004d9 /* U+04D9 CYRILLIC SMALL LETTER SCHWA */ +#define XK_Cyrillic_I_macron 0x10004e2 /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */ +#define XK_Cyrillic_i_macron 0x10004e3 /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */ +#define XK_Cyrillic_O_bar 0x10004e8 /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */ +#define XK_Cyrillic_o_bar 0x10004e9 /* U+04E9 CYRILLIC SMALL LETTER BARRED O */ +#define XK_Cyrillic_U_macron 0x10004ee /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */ +#define XK_Cyrillic_u_macron 0x10004ef /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */ + +#define XK_Serbian_dje 0x06a1 /* U+0452 CYRILLIC SMALL LETTER DJE */ +#define XK_Macedonia_gje 0x06a2 /* U+0453 CYRILLIC SMALL LETTER GJE */ +#define XK_Cyrillic_io 0x06a3 /* U+0451 CYRILLIC SMALL LETTER IO */ +#define XK_Ukrainian_ie 0x06a4 /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */ +#define XK_Ukranian_je 0x06a4 /* deprecated */ +#define XK_Macedonia_dse 0x06a5 /* U+0455 CYRILLIC SMALL LETTER DZE */ +#define XK_Ukrainian_i 0x06a6 /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ +#define XK_Ukranian_i 0x06a6 /* deprecated */ +#define XK_Ukrainian_yi 0x06a7 /* U+0457 CYRILLIC SMALL LETTER YI */ +#define XK_Ukranian_yi 0x06a7 /* deprecated */ +#define XK_Cyrillic_je 0x06a8 /* U+0458 CYRILLIC SMALL LETTER JE */ +#define XK_Serbian_je 0x06a8 /* deprecated */ +#define XK_Cyrillic_lje 0x06a9 /* U+0459 CYRILLIC SMALL LETTER LJE */ +#define XK_Serbian_lje 0x06a9 /* deprecated */ +#define XK_Cyrillic_nje 0x06aa /* U+045A CYRILLIC SMALL LETTER NJE */ +#define XK_Serbian_nje 0x06aa /* deprecated */ +#define XK_Serbian_tshe 0x06ab /* U+045B CYRILLIC SMALL LETTER TSHE */ +#define XK_Macedonia_kje 0x06ac /* U+045C CYRILLIC SMALL LETTER KJE */ +#define XK_Ukrainian_ghe_with_upturn 0x06ad /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */ +#define XK_Byelorussian_shortu 0x06ae /* U+045E CYRILLIC SMALL LETTER SHORT U */ +#define XK_Cyrillic_dzhe 0x06af /* U+045F CYRILLIC SMALL LETTER DZHE */ +#define XK_Serbian_dze 0x06af /* deprecated */ +#define XK_numerosign 0x06b0 /* U+2116 NUMERO SIGN */ +#define XK_Serbian_DJE 0x06b1 /* U+0402 CYRILLIC CAPITAL LETTER DJE */ +#define XK_Macedonia_GJE 0x06b2 /* U+0403 CYRILLIC CAPITAL LETTER GJE */ +#define XK_Cyrillic_IO 0x06b3 /* U+0401 CYRILLIC CAPITAL LETTER IO */ +#define XK_Ukrainian_IE 0x06b4 /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */ +#define XK_Ukranian_JE 0x06b4 /* deprecated */ +#define XK_Macedonia_DSE 0x06b5 /* U+0405 CYRILLIC CAPITAL LETTER DZE */ +#define XK_Ukrainian_I 0x06b6 /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ +#define XK_Ukranian_I 0x06b6 /* deprecated */ +#define XK_Ukrainian_YI 0x06b7 /* U+0407 CYRILLIC CAPITAL LETTER YI */ +#define XK_Ukranian_YI 0x06b7 /* deprecated */ +#define XK_Cyrillic_JE 0x06b8 /* U+0408 CYRILLIC CAPITAL LETTER JE */ +#define XK_Serbian_JE 0x06b8 /* deprecated */ +#define XK_Cyrillic_LJE 0x06b9 /* U+0409 CYRILLIC CAPITAL LETTER LJE */ +#define XK_Serbian_LJE 0x06b9 /* deprecated */ +#define XK_Cyrillic_NJE 0x06ba /* U+040A CYRILLIC CAPITAL LETTER NJE */ +#define XK_Serbian_NJE 0x06ba /* deprecated */ +#define XK_Serbian_TSHE 0x06bb /* U+040B CYRILLIC CAPITAL LETTER TSHE */ +#define XK_Macedonia_KJE 0x06bc /* U+040C CYRILLIC CAPITAL LETTER KJE */ +#define XK_Ukrainian_GHE_WITH_UPTURN 0x06bd /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ +#define XK_Byelorussian_SHORTU 0x06be /* U+040E CYRILLIC CAPITAL LETTER SHORT U */ +#define XK_Cyrillic_DZHE 0x06bf /* U+040F CYRILLIC CAPITAL LETTER DZHE */ +#define XK_Serbian_DZE 0x06bf /* deprecated */ +#define XK_Cyrillic_yu 0x06c0 /* U+044E CYRILLIC SMALL LETTER YU */ +#define XK_Cyrillic_a 0x06c1 /* U+0430 CYRILLIC SMALL LETTER A */ +#define XK_Cyrillic_be 0x06c2 /* U+0431 CYRILLIC SMALL LETTER BE */ +#define XK_Cyrillic_tse 0x06c3 /* U+0446 CYRILLIC SMALL LETTER TSE */ +#define XK_Cyrillic_de 0x06c4 /* U+0434 CYRILLIC SMALL LETTER DE */ +#define XK_Cyrillic_ie 0x06c5 /* U+0435 CYRILLIC SMALL LETTER IE */ +#define XK_Cyrillic_ef 0x06c6 /* U+0444 CYRILLIC SMALL LETTER EF */ +#define XK_Cyrillic_ghe 0x06c7 /* U+0433 CYRILLIC SMALL LETTER GHE */ +#define XK_Cyrillic_ha 0x06c8 /* U+0445 CYRILLIC SMALL LETTER HA */ +#define XK_Cyrillic_i 0x06c9 /* U+0438 CYRILLIC SMALL LETTER I */ +#define XK_Cyrillic_shorti 0x06ca /* U+0439 CYRILLIC SMALL LETTER SHORT I */ +#define XK_Cyrillic_ka 0x06cb /* U+043A CYRILLIC SMALL LETTER KA */ +#define XK_Cyrillic_el 0x06cc /* U+043B CYRILLIC SMALL LETTER EL */ +#define XK_Cyrillic_em 0x06cd /* U+043C CYRILLIC SMALL LETTER EM */ +#define XK_Cyrillic_en 0x06ce /* U+043D CYRILLIC SMALL LETTER EN */ +#define XK_Cyrillic_o 0x06cf /* U+043E CYRILLIC SMALL LETTER O */ +#define XK_Cyrillic_pe 0x06d0 /* U+043F CYRILLIC SMALL LETTER PE */ +#define XK_Cyrillic_ya 0x06d1 /* U+044F CYRILLIC SMALL LETTER YA */ +#define XK_Cyrillic_er 0x06d2 /* U+0440 CYRILLIC SMALL LETTER ER */ +#define XK_Cyrillic_es 0x06d3 /* U+0441 CYRILLIC SMALL LETTER ES */ +#define XK_Cyrillic_te 0x06d4 /* U+0442 CYRILLIC SMALL LETTER TE */ +#define XK_Cyrillic_u 0x06d5 /* U+0443 CYRILLIC SMALL LETTER U */ +#define XK_Cyrillic_zhe 0x06d6 /* U+0436 CYRILLIC SMALL LETTER ZHE */ +#define XK_Cyrillic_ve 0x06d7 /* U+0432 CYRILLIC SMALL LETTER VE */ +#define XK_Cyrillic_softsign 0x06d8 /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */ +#define XK_Cyrillic_yeru 0x06d9 /* U+044B CYRILLIC SMALL LETTER YERU */ +#define XK_Cyrillic_ze 0x06da /* U+0437 CYRILLIC SMALL LETTER ZE */ +#define XK_Cyrillic_sha 0x06db /* U+0448 CYRILLIC SMALL LETTER SHA */ +#define XK_Cyrillic_e 0x06dc /* U+044D CYRILLIC SMALL LETTER E */ +#define XK_Cyrillic_shcha 0x06dd /* U+0449 CYRILLIC SMALL LETTER SHCHA */ +#define XK_Cyrillic_che 0x06de /* U+0447 CYRILLIC SMALL LETTER CHE */ +#define XK_Cyrillic_hardsign 0x06df /* U+044A CYRILLIC SMALL LETTER HARD SIGN */ +#define XK_Cyrillic_YU 0x06e0 /* U+042E CYRILLIC CAPITAL LETTER YU */ +#define XK_Cyrillic_A 0x06e1 /* U+0410 CYRILLIC CAPITAL LETTER A */ +#define XK_Cyrillic_BE 0x06e2 /* U+0411 CYRILLIC CAPITAL LETTER BE */ +#define XK_Cyrillic_TSE 0x06e3 /* U+0426 CYRILLIC CAPITAL LETTER TSE */ +#define XK_Cyrillic_DE 0x06e4 /* U+0414 CYRILLIC CAPITAL LETTER DE */ +#define XK_Cyrillic_IE 0x06e5 /* U+0415 CYRILLIC CAPITAL LETTER IE */ +#define XK_Cyrillic_EF 0x06e6 /* U+0424 CYRILLIC CAPITAL LETTER EF */ +#define XK_Cyrillic_GHE 0x06e7 /* U+0413 CYRILLIC CAPITAL LETTER GHE */ +#define XK_Cyrillic_HA 0x06e8 /* U+0425 CYRILLIC CAPITAL LETTER HA */ +#define XK_Cyrillic_I 0x06e9 /* U+0418 CYRILLIC CAPITAL LETTER I */ +#define XK_Cyrillic_SHORTI 0x06ea /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */ +#define XK_Cyrillic_KA 0x06eb /* U+041A CYRILLIC CAPITAL LETTER KA */ +#define XK_Cyrillic_EL 0x06ec /* U+041B CYRILLIC CAPITAL LETTER EL */ +#define XK_Cyrillic_EM 0x06ed /* U+041C CYRILLIC CAPITAL LETTER EM */ +#define XK_Cyrillic_EN 0x06ee /* U+041D CYRILLIC CAPITAL LETTER EN */ +#define XK_Cyrillic_O 0x06ef /* U+041E CYRILLIC CAPITAL LETTER O */ +#define XK_Cyrillic_PE 0x06f0 /* U+041F CYRILLIC CAPITAL LETTER PE */ +#define XK_Cyrillic_YA 0x06f1 /* U+042F CYRILLIC CAPITAL LETTER YA */ +#define XK_Cyrillic_ER 0x06f2 /* U+0420 CYRILLIC CAPITAL LETTER ER */ +#define XK_Cyrillic_ES 0x06f3 /* U+0421 CYRILLIC CAPITAL LETTER ES */ +#define XK_Cyrillic_TE 0x06f4 /* U+0422 CYRILLIC CAPITAL LETTER TE */ +#define XK_Cyrillic_U 0x06f5 /* U+0423 CYRILLIC CAPITAL LETTER U */ +#define XK_Cyrillic_ZHE 0x06f6 /* U+0416 CYRILLIC CAPITAL LETTER ZHE */ +#define XK_Cyrillic_VE 0x06f7 /* U+0412 CYRILLIC CAPITAL LETTER VE */ +#define XK_Cyrillic_SOFTSIGN 0x06f8 /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */ +#define XK_Cyrillic_YERU 0x06f9 /* U+042B CYRILLIC CAPITAL LETTER YERU */ +#define XK_Cyrillic_ZE 0x06fa /* U+0417 CYRILLIC CAPITAL LETTER ZE */ +#define XK_Cyrillic_SHA 0x06fb /* U+0428 CYRILLIC CAPITAL LETTER SHA */ +#define XK_Cyrillic_E 0x06fc /* U+042D CYRILLIC CAPITAL LETTER E */ +#define XK_Cyrillic_SHCHA 0x06fd /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */ +#define XK_Cyrillic_CHE 0x06fe /* U+0427 CYRILLIC CAPITAL LETTER CHE */ +#define XK_Cyrillic_HARDSIGN 0x06ff /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */ +#endif /* XK_CYRILLIC */ + +/* + * Greek + * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7) + * Byte 3 = 7 + */ + +#ifdef XK_GREEK +#define XK_Greek_ALPHAaccent 0x07a1 /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */ +#define XK_Greek_EPSILONaccent 0x07a2 /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */ +#define XK_Greek_ETAaccent 0x07a3 /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */ +#define XK_Greek_IOTAaccent 0x07a4 /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */ +#define XK_Greek_IOTAdieresis 0x07a5 /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ +#define XK_Greek_IOTAdiaeresis 0x07a5 /* old typo */ +#define XK_Greek_OMICRONaccent 0x07a7 /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */ +#define XK_Greek_UPSILONaccent 0x07a8 /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */ +#define XK_Greek_UPSILONdieresis 0x07a9 /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ +#define XK_Greek_OMEGAaccent 0x07ab /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */ +#define XK_Greek_accentdieresis 0x07ae /* U+0385 GREEK DIALYTIKA TONOS */ +#define XK_Greek_horizbar 0x07af /* U+2015 HORIZONTAL BAR */ +#define XK_Greek_alphaaccent 0x07b1 /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */ +#define XK_Greek_epsilonaccent 0x07b2 /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */ +#define XK_Greek_etaaccent 0x07b3 /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */ +#define XK_Greek_iotaaccent 0x07b4 /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */ +#define XK_Greek_iotadieresis 0x07b5 /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */ +#define XK_Greek_iotaaccentdieresis 0x07b6 /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ +#define XK_Greek_omicronaccent 0x07b7 /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */ +#define XK_Greek_upsilonaccent 0x07b8 /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */ +#define XK_Greek_upsilondieresis 0x07b9 /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ +#define XK_Greek_upsilonaccentdieresis 0x07ba /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ +#define XK_Greek_omegaaccent 0x07bb /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */ +#define XK_Greek_ALPHA 0x07c1 /* U+0391 GREEK CAPITAL LETTER ALPHA */ +#define XK_Greek_BETA 0x07c2 /* U+0392 GREEK CAPITAL LETTER BETA */ +#define XK_Greek_GAMMA 0x07c3 /* U+0393 GREEK CAPITAL LETTER GAMMA */ +#define XK_Greek_DELTA 0x07c4 /* U+0394 GREEK CAPITAL LETTER DELTA */ +#define XK_Greek_EPSILON 0x07c5 /* U+0395 GREEK CAPITAL LETTER EPSILON */ +#define XK_Greek_ZETA 0x07c6 /* U+0396 GREEK CAPITAL LETTER ZETA */ +#define XK_Greek_ETA 0x07c7 /* U+0397 GREEK CAPITAL LETTER ETA */ +#define XK_Greek_THETA 0x07c8 /* U+0398 GREEK CAPITAL LETTER THETA */ +#define XK_Greek_IOTA 0x07c9 /* U+0399 GREEK CAPITAL LETTER IOTA */ +#define XK_Greek_KAPPA 0x07ca /* U+039A GREEK CAPITAL LETTER KAPPA */ +#define XK_Greek_LAMDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ +#define XK_Greek_LAMBDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ +#define XK_Greek_MU 0x07cc /* U+039C GREEK CAPITAL LETTER MU */ +#define XK_Greek_NU 0x07cd /* U+039D GREEK CAPITAL LETTER NU */ +#define XK_Greek_XI 0x07ce /* U+039E GREEK CAPITAL LETTER XI */ +#define XK_Greek_OMICRON 0x07cf /* U+039F GREEK CAPITAL LETTER OMICRON */ +#define XK_Greek_PI 0x07d0 /* U+03A0 GREEK CAPITAL LETTER PI */ +#define XK_Greek_RHO 0x07d1 /* U+03A1 GREEK CAPITAL LETTER RHO */ +#define XK_Greek_SIGMA 0x07d2 /* U+03A3 GREEK CAPITAL LETTER SIGMA */ +#define XK_Greek_TAU 0x07d4 /* U+03A4 GREEK CAPITAL LETTER TAU */ +#define XK_Greek_UPSILON 0x07d5 /* U+03A5 GREEK CAPITAL LETTER UPSILON */ +#define XK_Greek_PHI 0x07d6 /* U+03A6 GREEK CAPITAL LETTER PHI */ +#define XK_Greek_CHI 0x07d7 /* U+03A7 GREEK CAPITAL LETTER CHI */ +#define XK_Greek_PSI 0x07d8 /* U+03A8 GREEK CAPITAL LETTER PSI */ +#define XK_Greek_OMEGA 0x07d9 /* U+03A9 GREEK CAPITAL LETTER OMEGA */ +#define XK_Greek_alpha 0x07e1 /* U+03B1 GREEK SMALL LETTER ALPHA */ +#define XK_Greek_beta 0x07e2 /* U+03B2 GREEK SMALL LETTER BETA */ +#define XK_Greek_gamma 0x07e3 /* U+03B3 GREEK SMALL LETTER GAMMA */ +#define XK_Greek_delta 0x07e4 /* U+03B4 GREEK SMALL LETTER DELTA */ +#define XK_Greek_epsilon 0x07e5 /* U+03B5 GREEK SMALL LETTER EPSILON */ +#define XK_Greek_zeta 0x07e6 /* U+03B6 GREEK SMALL LETTER ZETA */ +#define XK_Greek_eta 0x07e7 /* U+03B7 GREEK SMALL LETTER ETA */ +#define XK_Greek_theta 0x07e8 /* U+03B8 GREEK SMALL LETTER THETA */ +#define XK_Greek_iota 0x07e9 /* U+03B9 GREEK SMALL LETTER IOTA */ +#define XK_Greek_kappa 0x07ea /* U+03BA GREEK SMALL LETTER KAPPA */ +#define XK_Greek_lamda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ +#define XK_Greek_lambda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ +#define XK_Greek_mu 0x07ec /* U+03BC GREEK SMALL LETTER MU */ +#define XK_Greek_nu 0x07ed /* U+03BD GREEK SMALL LETTER NU */ +#define XK_Greek_xi 0x07ee /* U+03BE GREEK SMALL LETTER XI */ +#define XK_Greek_omicron 0x07ef /* U+03BF GREEK SMALL LETTER OMICRON */ +#define XK_Greek_pi 0x07f0 /* U+03C0 GREEK SMALL LETTER PI */ +#define XK_Greek_rho 0x07f1 /* U+03C1 GREEK SMALL LETTER RHO */ +#define XK_Greek_sigma 0x07f2 /* U+03C3 GREEK SMALL LETTER SIGMA */ +#define XK_Greek_finalsmallsigma 0x07f3 /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */ +#define XK_Greek_tau 0x07f4 /* U+03C4 GREEK SMALL LETTER TAU */ +#define XK_Greek_upsilon 0x07f5 /* U+03C5 GREEK SMALL LETTER UPSILON */ +#define XK_Greek_phi 0x07f6 /* U+03C6 GREEK SMALL LETTER PHI */ +#define XK_Greek_chi 0x07f7 /* U+03C7 GREEK SMALL LETTER CHI */ +#define XK_Greek_psi 0x07f8 /* U+03C8 GREEK SMALL LETTER PSI */ +#define XK_Greek_omega 0x07f9 /* U+03C9 GREEK SMALL LETTER OMEGA */ +#define XK_Greek_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_GREEK */ + +/* + * Technical + * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html) + * Byte 3 = 8 + */ + +#ifdef XK_TECHNICAL +#define XK_leftradical 0x08a1 /* U+23B7 RADICAL SYMBOL BOTTOM */ +#define XK_topleftradical 0x08a2 /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/ +#define XK_horizconnector 0x08a3 /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/ +#define XK_topintegral 0x08a4 /* U+2320 TOP HALF INTEGRAL */ +#define XK_botintegral 0x08a5 /* U+2321 BOTTOM HALF INTEGRAL */ +#define XK_vertconnector 0x08a6 /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/ +#define XK_topleftsqbracket 0x08a7 /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */ +#define XK_botleftsqbracket 0x08a8 /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */ +#define XK_toprightsqbracket 0x08a9 /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */ +#define XK_botrightsqbracket 0x08aa /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */ +#define XK_topleftparens 0x08ab /* U+239B LEFT PARENTHESIS UPPER HOOK */ +#define XK_botleftparens 0x08ac /* U+239D LEFT PARENTHESIS LOWER HOOK */ +#define XK_toprightparens 0x08ad /* U+239E RIGHT PARENTHESIS UPPER HOOK */ +#define XK_botrightparens 0x08ae /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */ +#define XK_leftmiddlecurlybrace 0x08af /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */ +#define XK_rightmiddlecurlybrace 0x08b0 /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */ +#define XK_topleftsummation 0x08b1 +#define XK_botleftsummation 0x08b2 +#define XK_topvertsummationconnector 0x08b3 +#define XK_botvertsummationconnector 0x08b4 +#define XK_toprightsummation 0x08b5 +#define XK_botrightsummation 0x08b6 +#define XK_rightmiddlesummation 0x08b7 +#define XK_lessthanequal 0x08bc /* U+2264 LESS-THAN OR EQUAL TO */ +#define XK_notequal 0x08bd /* U+2260 NOT EQUAL TO */ +#define XK_greaterthanequal 0x08be /* U+2265 GREATER-THAN OR EQUAL TO */ +#define XK_integral 0x08bf /* U+222B INTEGRAL */ +#define XK_therefore 0x08c0 /* U+2234 THEREFORE */ +#define XK_variation 0x08c1 /* U+221D PROPORTIONAL TO */ +#define XK_infinity 0x08c2 /* U+221E INFINITY */ +#define XK_nabla 0x08c5 /* U+2207 NABLA */ +#define XK_approximate 0x08c8 /* U+223C TILDE OPERATOR */ +#define XK_similarequal 0x08c9 /* U+2243 ASYMPTOTICALLY EQUAL TO */ +#define XK_ifonlyif 0x08cd /* U+21D4 LEFT RIGHT DOUBLE ARROW */ +#define XK_implies 0x08ce /* U+21D2 RIGHTWARDS DOUBLE ARROW */ +#define XK_identical 0x08cf /* U+2261 IDENTICAL TO */ +#define XK_radical 0x08d6 /* U+221A SQUARE ROOT */ +#define XK_includedin 0x08da /* U+2282 SUBSET OF */ +#define XK_includes 0x08db /* U+2283 SUPERSET OF */ +#define XK_intersection 0x08dc /* U+2229 INTERSECTION */ +#define XK_union 0x08dd /* U+222A UNION */ +#define XK_logicaland 0x08de /* U+2227 LOGICAL AND */ +#define XK_logicalor 0x08df /* U+2228 LOGICAL OR */ +#define XK_partialderivative 0x08ef /* U+2202 PARTIAL DIFFERENTIAL */ +#define XK_function 0x08f6 /* U+0192 LATIN SMALL LETTER F WITH HOOK */ +#define XK_leftarrow 0x08fb /* U+2190 LEFTWARDS ARROW */ +#define XK_uparrow 0x08fc /* U+2191 UPWARDS ARROW */ +#define XK_rightarrow 0x08fd /* U+2192 RIGHTWARDS ARROW */ +#define XK_downarrow 0x08fe /* U+2193 DOWNWARDS ARROW */ +#endif /* XK_TECHNICAL */ + +/* + * Special + * (from the DEC VT100 Special Graphics Character Set) + * Byte 3 = 9 + */ + +#ifdef XK_SPECIAL +#define XK_blank 0x09df +#define XK_soliddiamond 0x09e0 /* U+25C6 BLACK DIAMOND */ +#define XK_checkerboard 0x09e1 /* U+2592 MEDIUM SHADE */ +#define XK_ht 0x09e2 /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */ +#define XK_ff 0x09e3 /* U+240C SYMBOL FOR FORM FEED */ +#define XK_cr 0x09e4 /* U+240D SYMBOL FOR CARRIAGE RETURN */ +#define XK_lf 0x09e5 /* U+240A SYMBOL FOR LINE FEED */ +#define XK_nl 0x09e8 /* U+2424 SYMBOL FOR NEWLINE */ +#define XK_vt 0x09e9 /* U+240B SYMBOL FOR VERTICAL TABULATION */ +#define XK_lowrightcorner 0x09ea /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */ +#define XK_uprightcorner 0x09eb /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */ +#define XK_upleftcorner 0x09ec /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */ +#define XK_lowleftcorner 0x09ed /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */ +#define XK_crossinglines 0x09ee /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ +#define XK_horizlinescan1 0x09ef /* U+23BA HORIZONTAL SCAN LINE-1 */ +#define XK_horizlinescan3 0x09f0 /* U+23BB HORIZONTAL SCAN LINE-3 */ +#define XK_horizlinescan5 0x09f1 /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */ +#define XK_horizlinescan7 0x09f2 /* U+23BC HORIZONTAL SCAN LINE-7 */ +#define XK_horizlinescan9 0x09f3 /* U+23BD HORIZONTAL SCAN LINE-9 */ +#define XK_leftt 0x09f4 /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ +#define XK_rightt 0x09f5 /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */ +#define XK_bott 0x09f6 /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */ +#define XK_topt 0x09f7 /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ +#define XK_vertbar 0x09f8 /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ +#endif /* XK_SPECIAL */ + +/* + * Publishing + * (these are probably from a long forgotten DEC Publishing + * font that once shipped with DECwrite) + * Byte 3 = 0x0a + */ + +#ifdef XK_PUBLISHING +#define XK_emspace 0x0aa1 /* U+2003 EM SPACE */ +#define XK_enspace 0x0aa2 /* U+2002 EN SPACE */ +#define XK_em3space 0x0aa3 /* U+2004 THREE-PER-EM SPACE */ +#define XK_em4space 0x0aa4 /* U+2005 FOUR-PER-EM SPACE */ +#define XK_digitspace 0x0aa5 /* U+2007 FIGURE SPACE */ +#define XK_punctspace 0x0aa6 /* U+2008 PUNCTUATION SPACE */ +#define XK_thinspace 0x0aa7 /* U+2009 THIN SPACE */ +#define XK_hairspace 0x0aa8 /* U+200A HAIR SPACE */ +#define XK_emdash 0x0aa9 /* U+2014 EM DASH */ +#define XK_endash 0x0aaa /* U+2013 EN DASH */ +#define XK_signifblank 0x0aac /*(U+2423 OPEN BOX)*/ +#define XK_ellipsis 0x0aae /* U+2026 HORIZONTAL ELLIPSIS */ +#define XK_doubbaselinedot 0x0aaf /* U+2025 TWO DOT LEADER */ +#define XK_onethird 0x0ab0 /* U+2153 VULGAR FRACTION ONE THIRD */ +#define XK_twothirds 0x0ab1 /* U+2154 VULGAR FRACTION TWO THIRDS */ +#define XK_onefifth 0x0ab2 /* U+2155 VULGAR FRACTION ONE FIFTH */ +#define XK_twofifths 0x0ab3 /* U+2156 VULGAR FRACTION TWO FIFTHS */ +#define XK_threefifths 0x0ab4 /* U+2157 VULGAR FRACTION THREE FIFTHS */ +#define XK_fourfifths 0x0ab5 /* U+2158 VULGAR FRACTION FOUR FIFTHS */ +#define XK_onesixth 0x0ab6 /* U+2159 VULGAR FRACTION ONE SIXTH */ +#define XK_fivesixths 0x0ab7 /* U+215A VULGAR FRACTION FIVE SIXTHS */ +#define XK_careof 0x0ab8 /* U+2105 CARE OF */ +#define XK_figdash 0x0abb /* U+2012 FIGURE DASH */ +#define XK_leftanglebracket 0x0abc /*(U+27E8 MATHEMATICAL LEFT ANGLE BRACKET)*/ +#define XK_decimalpoint 0x0abd /*(U+002E FULL STOP)*/ +#define XK_rightanglebracket 0x0abe /*(U+27E9 MATHEMATICAL RIGHT ANGLE BRACKET)*/ +#define XK_marker 0x0abf +#define XK_oneeighth 0x0ac3 /* U+215B VULGAR FRACTION ONE EIGHTH */ +#define XK_threeeighths 0x0ac4 /* U+215C VULGAR FRACTION THREE EIGHTHS */ +#define XK_fiveeighths 0x0ac5 /* U+215D VULGAR FRACTION FIVE EIGHTHS */ +#define XK_seveneighths 0x0ac6 /* U+215E VULGAR FRACTION SEVEN EIGHTHS */ +#define XK_trademark 0x0ac9 /* U+2122 TRADE MARK SIGN */ +#define XK_signaturemark 0x0aca /*(U+2613 SALTIRE)*/ +#define XK_trademarkincircle 0x0acb +#define XK_leftopentriangle 0x0acc /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/ +#define XK_rightopentriangle 0x0acd /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/ +#define XK_emopencircle 0x0ace /*(U+25CB WHITE CIRCLE)*/ +#define XK_emopenrectangle 0x0acf /*(U+25AF WHITE VERTICAL RECTANGLE)*/ +#define XK_leftsinglequotemark 0x0ad0 /* U+2018 LEFT SINGLE QUOTATION MARK */ +#define XK_rightsinglequotemark 0x0ad1 /* U+2019 RIGHT SINGLE QUOTATION MARK */ +#define XK_leftdoublequotemark 0x0ad2 /* U+201C LEFT DOUBLE QUOTATION MARK */ +#define XK_rightdoublequotemark 0x0ad3 /* U+201D RIGHT DOUBLE QUOTATION MARK */ +#define XK_prescription 0x0ad4 /* U+211E PRESCRIPTION TAKE */ +#define XK_minutes 0x0ad6 /* U+2032 PRIME */ +#define XK_seconds 0x0ad7 /* U+2033 DOUBLE PRIME */ +#define XK_latincross 0x0ad9 /* U+271D LATIN CROSS */ +#define XK_hexagram 0x0ada +#define XK_filledrectbullet 0x0adb /*(U+25AC BLACK RECTANGLE)*/ +#define XK_filledlefttribullet 0x0adc /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/ +#define XK_filledrighttribullet 0x0add /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/ +#define XK_emfilledcircle 0x0ade /*(U+25CF BLACK CIRCLE)*/ +#define XK_emfilledrect 0x0adf /*(U+25AE BLACK VERTICAL RECTANGLE)*/ +#define XK_enopencircbullet 0x0ae0 /*(U+25E6 WHITE BULLET)*/ +#define XK_enopensquarebullet 0x0ae1 /*(U+25AB WHITE SMALL SQUARE)*/ +#define XK_openrectbullet 0x0ae2 /*(U+25AD WHITE RECTANGLE)*/ +#define XK_opentribulletup 0x0ae3 /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/ +#define XK_opentribulletdown 0x0ae4 /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/ +#define XK_openstar 0x0ae5 /*(U+2606 WHITE STAR)*/ +#define XK_enfilledcircbullet 0x0ae6 /*(U+2022 BULLET)*/ +#define XK_enfilledsqbullet 0x0ae7 /*(U+25AA BLACK SMALL SQUARE)*/ +#define XK_filledtribulletup 0x0ae8 /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/ +#define XK_filledtribulletdown 0x0ae9 /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/ +#define XK_leftpointer 0x0aea /*(U+261C WHITE LEFT POINTING INDEX)*/ +#define XK_rightpointer 0x0aeb /*(U+261E WHITE RIGHT POINTING INDEX)*/ +#define XK_club 0x0aec /* U+2663 BLACK CLUB SUIT */ +#define XK_diamond 0x0aed /* U+2666 BLACK DIAMOND SUIT */ +#define XK_heart 0x0aee /* U+2665 BLACK HEART SUIT */ +#define XK_maltesecross 0x0af0 /* U+2720 MALTESE CROSS */ +#define XK_dagger 0x0af1 /* U+2020 DAGGER */ +#define XK_doubledagger 0x0af2 /* U+2021 DOUBLE DAGGER */ +#define XK_checkmark 0x0af3 /* U+2713 CHECK MARK */ +#define XK_ballotcross 0x0af4 /* U+2717 BALLOT X */ +#define XK_musicalsharp 0x0af5 /* U+266F MUSIC SHARP SIGN */ +#define XK_musicalflat 0x0af6 /* U+266D MUSIC FLAT SIGN */ +#define XK_malesymbol 0x0af7 /* U+2642 MALE SIGN */ +#define XK_femalesymbol 0x0af8 /* U+2640 FEMALE SIGN */ +#define XK_telephone 0x0af9 /* U+260E BLACK TELEPHONE */ +#define XK_telephonerecorder 0x0afa /* U+2315 TELEPHONE RECORDER */ +#define XK_phonographcopyright 0x0afb /* U+2117 SOUND RECORDING COPYRIGHT */ +#define XK_caret 0x0afc /* U+2038 CARET */ +#define XK_singlelowquotemark 0x0afd /* U+201A SINGLE LOW-9 QUOTATION MARK */ +#define XK_doublelowquotemark 0x0afe /* U+201E DOUBLE LOW-9 QUOTATION MARK */ +#define XK_cursor 0x0aff +#endif /* XK_PUBLISHING */ + +/* + * APL + * Byte 3 = 0x0b + */ + +#ifdef XK_APL +#define XK_leftcaret 0x0ba3 /*(U+003C LESS-THAN SIGN)*/ +#define XK_rightcaret 0x0ba6 /*(U+003E GREATER-THAN SIGN)*/ +#define XK_downcaret 0x0ba8 /*(U+2228 LOGICAL OR)*/ +#define XK_upcaret 0x0ba9 /*(U+2227 LOGICAL AND)*/ +#define XK_overbar 0x0bc0 /*(U+00AF MACRON)*/ +#define XK_downtack 0x0bc2 /* U+22A5 UP TACK */ +#define XK_upshoe 0x0bc3 /*(U+2229 INTERSECTION)*/ +#define XK_downstile 0x0bc4 /* U+230A LEFT FLOOR */ +#define XK_underbar 0x0bc6 /*(U+005F LOW LINE)*/ +#define XK_jot 0x0bca /* U+2218 RING OPERATOR */ +#define XK_quad 0x0bcc /* U+2395 APL FUNCTIONAL SYMBOL QUAD */ +#define XK_uptack 0x0bce /* U+22A4 DOWN TACK */ +#define XK_circle 0x0bcf /* U+25CB WHITE CIRCLE */ +#define XK_upstile 0x0bd3 /* U+2308 LEFT CEILING */ +#define XK_downshoe 0x0bd6 /*(U+222A UNION)*/ +#define XK_rightshoe 0x0bd8 /*(U+2283 SUPERSET OF)*/ +#define XK_leftshoe 0x0bda /*(U+2282 SUBSET OF)*/ +#define XK_lefttack 0x0bdc /* U+22A2 RIGHT TACK */ +#define XK_righttack 0x0bfc /* U+22A3 LEFT TACK */ +#endif /* XK_APL */ + +/* + * Hebrew + * Byte 3 = 0x0c + */ + +#ifdef XK_HEBREW +#define XK_hebrew_doublelowline 0x0cdf /* U+2017 DOUBLE LOW LINE */ +#define XK_hebrew_aleph 0x0ce0 /* U+05D0 HEBREW LETTER ALEF */ +#define XK_hebrew_bet 0x0ce1 /* U+05D1 HEBREW LETTER BET */ +#define XK_hebrew_beth 0x0ce1 /* deprecated */ +#define XK_hebrew_gimel 0x0ce2 /* U+05D2 HEBREW LETTER GIMEL */ +#define XK_hebrew_gimmel 0x0ce2 /* deprecated */ +#define XK_hebrew_dalet 0x0ce3 /* U+05D3 HEBREW LETTER DALET */ +#define XK_hebrew_daleth 0x0ce3 /* deprecated */ +#define XK_hebrew_he 0x0ce4 /* U+05D4 HEBREW LETTER HE */ +#define XK_hebrew_waw 0x0ce5 /* U+05D5 HEBREW LETTER VAV */ +#define XK_hebrew_zain 0x0ce6 /* U+05D6 HEBREW LETTER ZAYIN */ +#define XK_hebrew_zayin 0x0ce6 /* deprecated */ +#define XK_hebrew_chet 0x0ce7 /* U+05D7 HEBREW LETTER HET */ +#define XK_hebrew_het 0x0ce7 /* deprecated */ +#define XK_hebrew_tet 0x0ce8 /* U+05D8 HEBREW LETTER TET */ +#define XK_hebrew_teth 0x0ce8 /* deprecated */ +#define XK_hebrew_yod 0x0ce9 /* U+05D9 HEBREW LETTER YOD */ +#define XK_hebrew_finalkaph 0x0cea /* U+05DA HEBREW LETTER FINAL KAF */ +#define XK_hebrew_kaph 0x0ceb /* U+05DB HEBREW LETTER KAF */ +#define XK_hebrew_lamed 0x0cec /* U+05DC HEBREW LETTER LAMED */ +#define XK_hebrew_finalmem 0x0ced /* U+05DD HEBREW LETTER FINAL MEM */ +#define XK_hebrew_mem 0x0cee /* U+05DE HEBREW LETTER MEM */ +#define XK_hebrew_finalnun 0x0cef /* U+05DF HEBREW LETTER FINAL NUN */ +#define XK_hebrew_nun 0x0cf0 /* U+05E0 HEBREW LETTER NUN */ +#define XK_hebrew_samech 0x0cf1 /* U+05E1 HEBREW LETTER SAMEKH */ +#define XK_hebrew_samekh 0x0cf1 /* deprecated */ +#define XK_hebrew_ayin 0x0cf2 /* U+05E2 HEBREW LETTER AYIN */ +#define XK_hebrew_finalpe 0x0cf3 /* U+05E3 HEBREW LETTER FINAL PE */ +#define XK_hebrew_pe 0x0cf4 /* U+05E4 HEBREW LETTER PE */ +#define XK_hebrew_finalzade 0x0cf5 /* U+05E5 HEBREW LETTER FINAL TSADI */ +#define XK_hebrew_finalzadi 0x0cf5 /* deprecated */ +#define XK_hebrew_zade 0x0cf6 /* U+05E6 HEBREW LETTER TSADI */ +#define XK_hebrew_zadi 0x0cf6 /* deprecated */ +#define XK_hebrew_qoph 0x0cf7 /* U+05E7 HEBREW LETTER QOF */ +#define XK_hebrew_kuf 0x0cf7 /* deprecated */ +#define XK_hebrew_resh 0x0cf8 /* U+05E8 HEBREW LETTER RESH */ +#define XK_hebrew_shin 0x0cf9 /* U+05E9 HEBREW LETTER SHIN */ +#define XK_hebrew_taw 0x0cfa /* U+05EA HEBREW LETTER TAV */ +#define XK_hebrew_taf 0x0cfa /* deprecated */ +#define XK_Hebrew_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_HEBREW */ + +/* + * Thai + * Byte 3 = 0x0d + */ + +#ifdef XK_THAI +#define XK_Thai_kokai 0x0da1 /* U+0E01 THAI CHARACTER KO KAI */ +#define XK_Thai_khokhai 0x0da2 /* U+0E02 THAI CHARACTER KHO KHAI */ +#define XK_Thai_khokhuat 0x0da3 /* U+0E03 THAI CHARACTER KHO KHUAT */ +#define XK_Thai_khokhwai 0x0da4 /* U+0E04 THAI CHARACTER KHO KHWAI */ +#define XK_Thai_khokhon 0x0da5 /* U+0E05 THAI CHARACTER KHO KHON */ +#define XK_Thai_khorakhang 0x0da6 /* U+0E06 THAI CHARACTER KHO RAKHANG */ +#define XK_Thai_ngongu 0x0da7 /* U+0E07 THAI CHARACTER NGO NGU */ +#define XK_Thai_chochan 0x0da8 /* U+0E08 THAI CHARACTER CHO CHAN */ +#define XK_Thai_choching 0x0da9 /* U+0E09 THAI CHARACTER CHO CHING */ +#define XK_Thai_chochang 0x0daa /* U+0E0A THAI CHARACTER CHO CHANG */ +#define XK_Thai_soso 0x0dab /* U+0E0B THAI CHARACTER SO SO */ +#define XK_Thai_chochoe 0x0dac /* U+0E0C THAI CHARACTER CHO CHOE */ +#define XK_Thai_yoying 0x0dad /* U+0E0D THAI CHARACTER YO YING */ +#define XK_Thai_dochada 0x0dae /* U+0E0E THAI CHARACTER DO CHADA */ +#define XK_Thai_topatak 0x0daf /* U+0E0F THAI CHARACTER TO PATAK */ +#define XK_Thai_thothan 0x0db0 /* U+0E10 THAI CHARACTER THO THAN */ +#define XK_Thai_thonangmontho 0x0db1 /* U+0E11 THAI CHARACTER THO NANGMONTHO */ +#define XK_Thai_thophuthao 0x0db2 /* U+0E12 THAI CHARACTER THO PHUTHAO */ +#define XK_Thai_nonen 0x0db3 /* U+0E13 THAI CHARACTER NO NEN */ +#define XK_Thai_dodek 0x0db4 /* U+0E14 THAI CHARACTER DO DEK */ +#define XK_Thai_totao 0x0db5 /* U+0E15 THAI CHARACTER TO TAO */ +#define XK_Thai_thothung 0x0db6 /* U+0E16 THAI CHARACTER THO THUNG */ +#define XK_Thai_thothahan 0x0db7 /* U+0E17 THAI CHARACTER THO THAHAN */ +#define XK_Thai_thothong 0x0db8 /* U+0E18 THAI CHARACTER THO THONG */ +#define XK_Thai_nonu 0x0db9 /* U+0E19 THAI CHARACTER NO NU */ +#define XK_Thai_bobaimai 0x0dba /* U+0E1A THAI CHARACTER BO BAIMAI */ +#define XK_Thai_popla 0x0dbb /* U+0E1B THAI CHARACTER PO PLA */ +#define XK_Thai_phophung 0x0dbc /* U+0E1C THAI CHARACTER PHO PHUNG */ +#define XK_Thai_fofa 0x0dbd /* U+0E1D THAI CHARACTER FO FA */ +#define XK_Thai_phophan 0x0dbe /* U+0E1E THAI CHARACTER PHO PHAN */ +#define XK_Thai_fofan 0x0dbf /* U+0E1F THAI CHARACTER FO FAN */ +#define XK_Thai_phosamphao 0x0dc0 /* U+0E20 THAI CHARACTER PHO SAMPHAO */ +#define XK_Thai_moma 0x0dc1 /* U+0E21 THAI CHARACTER MO MA */ +#define XK_Thai_yoyak 0x0dc2 /* U+0E22 THAI CHARACTER YO YAK */ +#define XK_Thai_rorua 0x0dc3 /* U+0E23 THAI CHARACTER RO RUA */ +#define XK_Thai_ru 0x0dc4 /* U+0E24 THAI CHARACTER RU */ +#define XK_Thai_loling 0x0dc5 /* U+0E25 THAI CHARACTER LO LING */ +#define XK_Thai_lu 0x0dc6 /* U+0E26 THAI CHARACTER LU */ +#define XK_Thai_wowaen 0x0dc7 /* U+0E27 THAI CHARACTER WO WAEN */ +#define XK_Thai_sosala 0x0dc8 /* U+0E28 THAI CHARACTER SO SALA */ +#define XK_Thai_sorusi 0x0dc9 /* U+0E29 THAI CHARACTER SO RUSI */ +#define XK_Thai_sosua 0x0dca /* U+0E2A THAI CHARACTER SO SUA */ +#define XK_Thai_hohip 0x0dcb /* U+0E2B THAI CHARACTER HO HIP */ +#define XK_Thai_lochula 0x0dcc /* U+0E2C THAI CHARACTER LO CHULA */ +#define XK_Thai_oang 0x0dcd /* U+0E2D THAI CHARACTER O ANG */ +#define XK_Thai_honokhuk 0x0dce /* U+0E2E THAI CHARACTER HO NOKHUK */ +#define XK_Thai_paiyannoi 0x0dcf /* U+0E2F THAI CHARACTER PAIYANNOI */ +#define XK_Thai_saraa 0x0dd0 /* U+0E30 THAI CHARACTER SARA A */ +#define XK_Thai_maihanakat 0x0dd1 /* U+0E31 THAI CHARACTER MAI HAN-AKAT */ +#define XK_Thai_saraaa 0x0dd2 /* U+0E32 THAI CHARACTER SARA AA */ +#define XK_Thai_saraam 0x0dd3 /* U+0E33 THAI CHARACTER SARA AM */ +#define XK_Thai_sarai 0x0dd4 /* U+0E34 THAI CHARACTER SARA I */ +#define XK_Thai_saraii 0x0dd5 /* U+0E35 THAI CHARACTER SARA II */ +#define XK_Thai_saraue 0x0dd6 /* U+0E36 THAI CHARACTER SARA UE */ +#define XK_Thai_sarauee 0x0dd7 /* U+0E37 THAI CHARACTER SARA UEE */ +#define XK_Thai_sarau 0x0dd8 /* U+0E38 THAI CHARACTER SARA U */ +#define XK_Thai_sarauu 0x0dd9 /* U+0E39 THAI CHARACTER SARA UU */ +#define XK_Thai_phinthu 0x0dda /* U+0E3A THAI CHARACTER PHINTHU */ +#define XK_Thai_maihanakat_maitho 0x0dde +#define XK_Thai_baht 0x0ddf /* U+0E3F THAI CURRENCY SYMBOL BAHT */ +#define XK_Thai_sarae 0x0de0 /* U+0E40 THAI CHARACTER SARA E */ +#define XK_Thai_saraae 0x0de1 /* U+0E41 THAI CHARACTER SARA AE */ +#define XK_Thai_sarao 0x0de2 /* U+0E42 THAI CHARACTER SARA O */ +#define XK_Thai_saraaimaimuan 0x0de3 /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */ +#define XK_Thai_saraaimaimalai 0x0de4 /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */ +#define XK_Thai_lakkhangyao 0x0de5 /* U+0E45 THAI CHARACTER LAKKHANGYAO */ +#define XK_Thai_maiyamok 0x0de6 /* U+0E46 THAI CHARACTER MAIYAMOK */ +#define XK_Thai_maitaikhu 0x0de7 /* U+0E47 THAI CHARACTER MAITAIKHU */ +#define XK_Thai_maiek 0x0de8 /* U+0E48 THAI CHARACTER MAI EK */ +#define XK_Thai_maitho 0x0de9 /* U+0E49 THAI CHARACTER MAI THO */ +#define XK_Thai_maitri 0x0dea /* U+0E4A THAI CHARACTER MAI TRI */ +#define XK_Thai_maichattawa 0x0deb /* U+0E4B THAI CHARACTER MAI CHATTAWA */ +#define XK_Thai_thanthakhat 0x0dec /* U+0E4C THAI CHARACTER THANTHAKHAT */ +#define XK_Thai_nikhahit 0x0ded /* U+0E4D THAI CHARACTER NIKHAHIT */ +#define XK_Thai_leksun 0x0df0 /* U+0E50 THAI DIGIT ZERO */ +#define XK_Thai_leknung 0x0df1 /* U+0E51 THAI DIGIT ONE */ +#define XK_Thai_leksong 0x0df2 /* U+0E52 THAI DIGIT TWO */ +#define XK_Thai_leksam 0x0df3 /* U+0E53 THAI DIGIT THREE */ +#define XK_Thai_leksi 0x0df4 /* U+0E54 THAI DIGIT FOUR */ +#define XK_Thai_lekha 0x0df5 /* U+0E55 THAI DIGIT FIVE */ +#define XK_Thai_lekhok 0x0df6 /* U+0E56 THAI DIGIT SIX */ +#define XK_Thai_lekchet 0x0df7 /* U+0E57 THAI DIGIT SEVEN */ +#define XK_Thai_lekpaet 0x0df8 /* U+0E58 THAI DIGIT EIGHT */ +#define XK_Thai_lekkao 0x0df9 /* U+0E59 THAI DIGIT NINE */ +#endif /* XK_THAI */ + +/* + * Korean + * Byte 3 = 0x0e + */ + +#ifdef XK_KOREAN + +#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */ +#define XK_Hangul_Start 0xff32 /* Hangul start */ +#define XK_Hangul_End 0xff33 /* Hangul end, English start */ +#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xff7e /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0x0ea1 +#define XK_Hangul_SsangKiyeog 0x0ea2 +#define XK_Hangul_KiyeogSios 0x0ea3 +#define XK_Hangul_Nieun 0x0ea4 +#define XK_Hangul_NieunJieuj 0x0ea5 +#define XK_Hangul_NieunHieuh 0x0ea6 +#define XK_Hangul_Dikeud 0x0ea7 +#define XK_Hangul_SsangDikeud 0x0ea8 +#define XK_Hangul_Rieul 0x0ea9 +#define XK_Hangul_RieulKiyeog 0x0eaa +#define XK_Hangul_RieulMieum 0x0eab +#define XK_Hangul_RieulPieub 0x0eac +#define XK_Hangul_RieulSios 0x0ead +#define XK_Hangul_RieulTieut 0x0eae +#define XK_Hangul_RieulPhieuf 0x0eaf +#define XK_Hangul_RieulHieuh 0x0eb0 +#define XK_Hangul_Mieum 0x0eb1 +#define XK_Hangul_Pieub 0x0eb2 +#define XK_Hangul_SsangPieub 0x0eb3 +#define XK_Hangul_PieubSios 0x0eb4 +#define XK_Hangul_Sios 0x0eb5 +#define XK_Hangul_SsangSios 0x0eb6 +#define XK_Hangul_Ieung 0x0eb7 +#define XK_Hangul_Jieuj 0x0eb8 +#define XK_Hangul_SsangJieuj 0x0eb9 +#define XK_Hangul_Cieuc 0x0eba +#define XK_Hangul_Khieuq 0x0ebb +#define XK_Hangul_Tieut 0x0ebc +#define XK_Hangul_Phieuf 0x0ebd +#define XK_Hangul_Hieuh 0x0ebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0x0ebf +#define XK_Hangul_AE 0x0ec0 +#define XK_Hangul_YA 0x0ec1 +#define XK_Hangul_YAE 0x0ec2 +#define XK_Hangul_EO 0x0ec3 +#define XK_Hangul_E 0x0ec4 +#define XK_Hangul_YEO 0x0ec5 +#define XK_Hangul_YE 0x0ec6 +#define XK_Hangul_O 0x0ec7 +#define XK_Hangul_WA 0x0ec8 +#define XK_Hangul_WAE 0x0ec9 +#define XK_Hangul_OE 0x0eca +#define XK_Hangul_YO 0x0ecb +#define XK_Hangul_U 0x0ecc +#define XK_Hangul_WEO 0x0ecd +#define XK_Hangul_WE 0x0ece +#define XK_Hangul_WI 0x0ecf +#define XK_Hangul_YU 0x0ed0 +#define XK_Hangul_EU 0x0ed1 +#define XK_Hangul_YI 0x0ed2 +#define XK_Hangul_I 0x0ed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0x0ed4 +#define XK_Hangul_J_SsangKiyeog 0x0ed5 +#define XK_Hangul_J_KiyeogSios 0x0ed6 +#define XK_Hangul_J_Nieun 0x0ed7 +#define XK_Hangul_J_NieunJieuj 0x0ed8 +#define XK_Hangul_J_NieunHieuh 0x0ed9 +#define XK_Hangul_J_Dikeud 0x0eda +#define XK_Hangul_J_Rieul 0x0edb +#define XK_Hangul_J_RieulKiyeog 0x0edc +#define XK_Hangul_J_RieulMieum 0x0edd +#define XK_Hangul_J_RieulPieub 0x0ede +#define XK_Hangul_J_RieulSios 0x0edf +#define XK_Hangul_J_RieulTieut 0x0ee0 +#define XK_Hangul_J_RieulPhieuf 0x0ee1 +#define XK_Hangul_J_RieulHieuh 0x0ee2 +#define XK_Hangul_J_Mieum 0x0ee3 +#define XK_Hangul_J_Pieub 0x0ee4 +#define XK_Hangul_J_PieubSios 0x0ee5 +#define XK_Hangul_J_Sios 0x0ee6 +#define XK_Hangul_J_SsangSios 0x0ee7 +#define XK_Hangul_J_Ieung 0x0ee8 +#define XK_Hangul_J_Jieuj 0x0ee9 +#define XK_Hangul_J_Cieuc 0x0eea +#define XK_Hangul_J_Khieuq 0x0eeb +#define XK_Hangul_J_Tieut 0x0eec +#define XK_Hangul_J_Phieuf 0x0eed +#define XK_Hangul_J_Hieuh 0x0eee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0x0eef +#define XK_Hangul_SunkyeongeumMieum 0x0ef0 +#define XK_Hangul_SunkyeongeumPieub 0x0ef1 +#define XK_Hangul_PanSios 0x0ef2 +#define XK_Hangul_KkogjiDalrinIeung 0x0ef3 +#define XK_Hangul_SunkyeongeumPhieuf 0x0ef4 +#define XK_Hangul_YeorinHieuh 0x0ef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0x0ef6 +#define XK_Hangul_AraeAE 0x0ef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0x0ef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0x0ef9 +#define XK_Hangul_J_YeorinHieuh 0x0efa + +/* Korean currency symbol */ +#define XK_Korean_Won 0x0eff /*(U+20A9 WON SIGN)*/ + +#endif /* XK_KOREAN */ + +/* + * Armenian + */ + +#ifdef XK_ARMENIAN +#define XK_Armenian_ligature_ew 0x1000587 /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */ +#define XK_Armenian_full_stop 0x1000589 /* U+0589 ARMENIAN FULL STOP */ +#define XK_Armenian_verjaket 0x1000589 /* U+0589 ARMENIAN FULL STOP */ +#define XK_Armenian_separation_mark 0x100055d /* U+055D ARMENIAN COMMA */ +#define XK_Armenian_but 0x100055d /* U+055D ARMENIAN COMMA */ +#define XK_Armenian_hyphen 0x100058a /* U+058A ARMENIAN HYPHEN */ +#define XK_Armenian_yentamna 0x100058a /* U+058A ARMENIAN HYPHEN */ +#define XK_Armenian_exclam 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ +#define XK_Armenian_amanak 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ +#define XK_Armenian_accent 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ +#define XK_Armenian_shesht 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ +#define XK_Armenian_question 0x100055e /* U+055E ARMENIAN QUESTION MARK */ +#define XK_Armenian_paruyk 0x100055e /* U+055E ARMENIAN QUESTION MARK */ +#define XK_Armenian_AYB 0x1000531 /* U+0531 ARMENIAN CAPITAL LETTER AYB */ +#define XK_Armenian_ayb 0x1000561 /* U+0561 ARMENIAN SMALL LETTER AYB */ +#define XK_Armenian_BEN 0x1000532 /* U+0532 ARMENIAN CAPITAL LETTER BEN */ +#define XK_Armenian_ben 0x1000562 /* U+0562 ARMENIAN SMALL LETTER BEN */ +#define XK_Armenian_GIM 0x1000533 /* U+0533 ARMENIAN CAPITAL LETTER GIM */ +#define XK_Armenian_gim 0x1000563 /* U+0563 ARMENIAN SMALL LETTER GIM */ +#define XK_Armenian_DA 0x1000534 /* U+0534 ARMENIAN CAPITAL LETTER DA */ +#define XK_Armenian_da 0x1000564 /* U+0564 ARMENIAN SMALL LETTER DA */ +#define XK_Armenian_YECH 0x1000535 /* U+0535 ARMENIAN CAPITAL LETTER ECH */ +#define XK_Armenian_yech 0x1000565 /* U+0565 ARMENIAN SMALL LETTER ECH */ +#define XK_Armenian_ZA 0x1000536 /* U+0536 ARMENIAN CAPITAL LETTER ZA */ +#define XK_Armenian_za 0x1000566 /* U+0566 ARMENIAN SMALL LETTER ZA */ +#define XK_Armenian_E 0x1000537 /* U+0537 ARMENIAN CAPITAL LETTER EH */ +#define XK_Armenian_e 0x1000567 /* U+0567 ARMENIAN SMALL LETTER EH */ +#define XK_Armenian_AT 0x1000538 /* U+0538 ARMENIAN CAPITAL LETTER ET */ +#define XK_Armenian_at 0x1000568 /* U+0568 ARMENIAN SMALL LETTER ET */ +#define XK_Armenian_TO 0x1000539 /* U+0539 ARMENIAN CAPITAL LETTER TO */ +#define XK_Armenian_to 0x1000569 /* U+0569 ARMENIAN SMALL LETTER TO */ +#define XK_Armenian_ZHE 0x100053a /* U+053A ARMENIAN CAPITAL LETTER ZHE */ +#define XK_Armenian_zhe 0x100056a /* U+056A ARMENIAN SMALL LETTER ZHE */ +#define XK_Armenian_INI 0x100053b /* U+053B ARMENIAN CAPITAL LETTER INI */ +#define XK_Armenian_ini 0x100056b /* U+056B ARMENIAN SMALL LETTER INI */ +#define XK_Armenian_LYUN 0x100053c /* U+053C ARMENIAN CAPITAL LETTER LIWN */ +#define XK_Armenian_lyun 0x100056c /* U+056C ARMENIAN SMALL LETTER LIWN */ +#define XK_Armenian_KHE 0x100053d /* U+053D ARMENIAN CAPITAL LETTER XEH */ +#define XK_Armenian_khe 0x100056d /* U+056D ARMENIAN SMALL LETTER XEH */ +#define XK_Armenian_TSA 0x100053e /* U+053E ARMENIAN CAPITAL LETTER CA */ +#define XK_Armenian_tsa 0x100056e /* U+056E ARMENIAN SMALL LETTER CA */ +#define XK_Armenian_KEN 0x100053f /* U+053F ARMENIAN CAPITAL LETTER KEN */ +#define XK_Armenian_ken 0x100056f /* U+056F ARMENIAN SMALL LETTER KEN */ +#define XK_Armenian_HO 0x1000540 /* U+0540 ARMENIAN CAPITAL LETTER HO */ +#define XK_Armenian_ho 0x1000570 /* U+0570 ARMENIAN SMALL LETTER HO */ +#define XK_Armenian_DZA 0x1000541 /* U+0541 ARMENIAN CAPITAL LETTER JA */ +#define XK_Armenian_dza 0x1000571 /* U+0571 ARMENIAN SMALL LETTER JA */ +#define XK_Armenian_GHAT 0x1000542 /* U+0542 ARMENIAN CAPITAL LETTER GHAD */ +#define XK_Armenian_ghat 0x1000572 /* U+0572 ARMENIAN SMALL LETTER GHAD */ +#define XK_Armenian_TCHE 0x1000543 /* U+0543 ARMENIAN CAPITAL LETTER CHEH */ +#define XK_Armenian_tche 0x1000573 /* U+0573 ARMENIAN SMALL LETTER CHEH */ +#define XK_Armenian_MEN 0x1000544 /* U+0544 ARMENIAN CAPITAL LETTER MEN */ +#define XK_Armenian_men 0x1000574 /* U+0574 ARMENIAN SMALL LETTER MEN */ +#define XK_Armenian_HI 0x1000545 /* U+0545 ARMENIAN CAPITAL LETTER YI */ +#define XK_Armenian_hi 0x1000575 /* U+0575 ARMENIAN SMALL LETTER YI */ +#define XK_Armenian_NU 0x1000546 /* U+0546 ARMENIAN CAPITAL LETTER NOW */ +#define XK_Armenian_nu 0x1000576 /* U+0576 ARMENIAN SMALL LETTER NOW */ +#define XK_Armenian_SHA 0x1000547 /* U+0547 ARMENIAN CAPITAL LETTER SHA */ +#define XK_Armenian_sha 0x1000577 /* U+0577 ARMENIAN SMALL LETTER SHA */ +#define XK_Armenian_VO 0x1000548 /* U+0548 ARMENIAN CAPITAL LETTER VO */ +#define XK_Armenian_vo 0x1000578 /* U+0578 ARMENIAN SMALL LETTER VO */ +#define XK_Armenian_CHA 0x1000549 /* U+0549 ARMENIAN CAPITAL LETTER CHA */ +#define XK_Armenian_cha 0x1000579 /* U+0579 ARMENIAN SMALL LETTER CHA */ +#define XK_Armenian_PE 0x100054a /* U+054A ARMENIAN CAPITAL LETTER PEH */ +#define XK_Armenian_pe 0x100057a /* U+057A ARMENIAN SMALL LETTER PEH */ +#define XK_Armenian_JE 0x100054b /* U+054B ARMENIAN CAPITAL LETTER JHEH */ +#define XK_Armenian_je 0x100057b /* U+057B ARMENIAN SMALL LETTER JHEH */ +#define XK_Armenian_RA 0x100054c /* U+054C ARMENIAN CAPITAL LETTER RA */ +#define XK_Armenian_ra 0x100057c /* U+057C ARMENIAN SMALL LETTER RA */ +#define XK_Armenian_SE 0x100054d /* U+054D ARMENIAN CAPITAL LETTER SEH */ +#define XK_Armenian_se 0x100057d /* U+057D ARMENIAN SMALL LETTER SEH */ +#define XK_Armenian_VEV 0x100054e /* U+054E ARMENIAN CAPITAL LETTER VEW */ +#define XK_Armenian_vev 0x100057e /* U+057E ARMENIAN SMALL LETTER VEW */ +#define XK_Armenian_TYUN 0x100054f /* U+054F ARMENIAN CAPITAL LETTER TIWN */ +#define XK_Armenian_tyun 0x100057f /* U+057F ARMENIAN SMALL LETTER TIWN */ +#define XK_Armenian_RE 0x1000550 /* U+0550 ARMENIAN CAPITAL LETTER REH */ +#define XK_Armenian_re 0x1000580 /* U+0580 ARMENIAN SMALL LETTER REH */ +#define XK_Armenian_TSO 0x1000551 /* U+0551 ARMENIAN CAPITAL LETTER CO */ +#define XK_Armenian_tso 0x1000581 /* U+0581 ARMENIAN SMALL LETTER CO */ +#define XK_Armenian_VYUN 0x1000552 /* U+0552 ARMENIAN CAPITAL LETTER YIWN */ +#define XK_Armenian_vyun 0x1000582 /* U+0582 ARMENIAN SMALL LETTER YIWN */ +#define XK_Armenian_PYUR 0x1000553 /* U+0553 ARMENIAN CAPITAL LETTER PIWR */ +#define XK_Armenian_pyur 0x1000583 /* U+0583 ARMENIAN SMALL LETTER PIWR */ +#define XK_Armenian_KE 0x1000554 /* U+0554 ARMENIAN CAPITAL LETTER KEH */ +#define XK_Armenian_ke 0x1000584 /* U+0584 ARMENIAN SMALL LETTER KEH */ +#define XK_Armenian_O 0x1000555 /* U+0555 ARMENIAN CAPITAL LETTER OH */ +#define XK_Armenian_o 0x1000585 /* U+0585 ARMENIAN SMALL LETTER OH */ +#define XK_Armenian_FE 0x1000556 /* U+0556 ARMENIAN CAPITAL LETTER FEH */ +#define XK_Armenian_fe 0x1000586 /* U+0586 ARMENIAN SMALL LETTER FEH */ +#define XK_Armenian_apostrophe 0x100055a /* U+055A ARMENIAN APOSTROPHE */ +#endif /* XK_ARMENIAN */ + +/* + * Georgian + */ + +#ifdef XK_GEORGIAN +#define XK_Georgian_an 0x10010d0 /* U+10D0 GEORGIAN LETTER AN */ +#define XK_Georgian_ban 0x10010d1 /* U+10D1 GEORGIAN LETTER BAN */ +#define XK_Georgian_gan 0x10010d2 /* U+10D2 GEORGIAN LETTER GAN */ +#define XK_Georgian_don 0x10010d3 /* U+10D3 GEORGIAN LETTER DON */ +#define XK_Georgian_en 0x10010d4 /* U+10D4 GEORGIAN LETTER EN */ +#define XK_Georgian_vin 0x10010d5 /* U+10D5 GEORGIAN LETTER VIN */ +#define XK_Georgian_zen 0x10010d6 /* U+10D6 GEORGIAN LETTER ZEN */ +#define XK_Georgian_tan 0x10010d7 /* U+10D7 GEORGIAN LETTER TAN */ +#define XK_Georgian_in 0x10010d8 /* U+10D8 GEORGIAN LETTER IN */ +#define XK_Georgian_kan 0x10010d9 /* U+10D9 GEORGIAN LETTER KAN */ +#define XK_Georgian_las 0x10010da /* U+10DA GEORGIAN LETTER LAS */ +#define XK_Georgian_man 0x10010db /* U+10DB GEORGIAN LETTER MAN */ +#define XK_Georgian_nar 0x10010dc /* U+10DC GEORGIAN LETTER NAR */ +#define XK_Georgian_on 0x10010dd /* U+10DD GEORGIAN LETTER ON */ +#define XK_Georgian_par 0x10010de /* U+10DE GEORGIAN LETTER PAR */ +#define XK_Georgian_zhar 0x10010df /* U+10DF GEORGIAN LETTER ZHAR */ +#define XK_Georgian_rae 0x10010e0 /* U+10E0 GEORGIAN LETTER RAE */ +#define XK_Georgian_san 0x10010e1 /* U+10E1 GEORGIAN LETTER SAN */ +#define XK_Georgian_tar 0x10010e2 /* U+10E2 GEORGIAN LETTER TAR */ +#define XK_Georgian_un 0x10010e3 /* U+10E3 GEORGIAN LETTER UN */ +#define XK_Georgian_phar 0x10010e4 /* U+10E4 GEORGIAN LETTER PHAR */ +#define XK_Georgian_khar 0x10010e5 /* U+10E5 GEORGIAN LETTER KHAR */ +#define XK_Georgian_ghan 0x10010e6 /* U+10E6 GEORGIAN LETTER GHAN */ +#define XK_Georgian_qar 0x10010e7 /* U+10E7 GEORGIAN LETTER QAR */ +#define XK_Georgian_shin 0x10010e8 /* U+10E8 GEORGIAN LETTER SHIN */ +#define XK_Georgian_chin 0x10010e9 /* U+10E9 GEORGIAN LETTER CHIN */ +#define XK_Georgian_can 0x10010ea /* U+10EA GEORGIAN LETTER CAN */ +#define XK_Georgian_jil 0x10010eb /* U+10EB GEORGIAN LETTER JIL */ +#define XK_Georgian_cil 0x10010ec /* U+10EC GEORGIAN LETTER CIL */ +#define XK_Georgian_char 0x10010ed /* U+10ED GEORGIAN LETTER CHAR */ +#define XK_Georgian_xan 0x10010ee /* U+10EE GEORGIAN LETTER XAN */ +#define XK_Georgian_jhan 0x10010ef /* U+10EF GEORGIAN LETTER JHAN */ +#define XK_Georgian_hae 0x10010f0 /* U+10F0 GEORGIAN LETTER HAE */ +#define XK_Georgian_he 0x10010f1 /* U+10F1 GEORGIAN LETTER HE */ +#define XK_Georgian_hie 0x10010f2 /* U+10F2 GEORGIAN LETTER HIE */ +#define XK_Georgian_we 0x10010f3 /* U+10F3 GEORGIAN LETTER WE */ +#define XK_Georgian_har 0x10010f4 /* U+10F4 GEORGIAN LETTER HAR */ +#define XK_Georgian_hoe 0x10010f5 /* U+10F5 GEORGIAN LETTER HOE */ +#define XK_Georgian_fi 0x10010f6 /* U+10F6 GEORGIAN LETTER FI */ +#endif /* XK_GEORGIAN */ + +/* + * Azeri (and other Turkic or Caucasian languages) + */ + +#ifdef XK_CAUCASUS +/* latin */ +#define XK_Xabovedot 0x1001e8a /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */ +#define XK_Ibreve 0x100012c /* U+012C LATIN CAPITAL LETTER I WITH BREVE */ +#define XK_Zstroke 0x10001b5 /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */ +#define XK_Gcaron 0x10001e6 /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */ +#define XK_Ocaron 0x10001d1 /* U+01D2 LATIN CAPITAL LETTER O WITH CARON */ +#define XK_Obarred 0x100019f /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */ +#define XK_xabovedot 0x1001e8b /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */ +#define XK_ibreve 0x100012d /* U+012D LATIN SMALL LETTER I WITH BREVE */ +#define XK_zstroke 0x10001b6 /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */ +#define XK_gcaron 0x10001e7 /* U+01E7 LATIN SMALL LETTER G WITH CARON */ +#define XK_ocaron 0x10001d2 /* U+01D2 LATIN SMALL LETTER O WITH CARON */ +#define XK_obarred 0x1000275 /* U+0275 LATIN SMALL LETTER BARRED O */ +#define XK_SCHWA 0x100018f /* U+018F LATIN CAPITAL LETTER SCHWA */ +#define XK_schwa 0x1000259 /* U+0259 LATIN SMALL LETTER SCHWA */ +/* those are not really Caucasus */ +/* For Inupiak */ +#define XK_Lbelowdot 0x1001e36 /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */ +#define XK_lbelowdot 0x1001e37 /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */ +#endif /* XK_CAUCASUS */ + +/* + * Vietnamese + */ + +#ifdef XK_VIETNAMESE +#define XK_Abelowdot 0x1001ea0 /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */ +#define XK_abelowdot 0x1001ea1 /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */ +#define XK_Ahook 0x1001ea2 /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */ +#define XK_ahook 0x1001ea3 /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */ +#define XK_Acircumflexacute 0x1001ea4 /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ +#define XK_acircumflexacute 0x1001ea5 /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ +#define XK_Acircumflexgrave 0x1001ea6 /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ +#define XK_acircumflexgrave 0x1001ea7 /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ +#define XK_Acircumflexhook 0x1001ea8 /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_acircumflexhook 0x1001ea9 /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_Acircumflextilde 0x1001eaa /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ +#define XK_acircumflextilde 0x1001eab /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ +#define XK_Acircumflexbelowdot 0x1001eac /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_acircumflexbelowdot 0x1001ead /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_Abreveacute 0x1001eae /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ +#define XK_abreveacute 0x1001eaf /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */ +#define XK_Abrevegrave 0x1001eb0 /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ +#define XK_abrevegrave 0x1001eb1 /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */ +#define XK_Abrevehook 0x1001eb2 /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ +#define XK_abrevehook 0x1001eb3 /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ +#define XK_Abrevetilde 0x1001eb4 /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ +#define XK_abrevetilde 0x1001eb5 /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */ +#define XK_Abrevebelowdot 0x1001eb6 /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ +#define XK_abrevebelowdot 0x1001eb7 /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ +#define XK_Ebelowdot 0x1001eb8 /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */ +#define XK_ebelowdot 0x1001eb9 /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */ +#define XK_Ehook 0x1001eba /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */ +#define XK_ehook 0x1001ebb /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */ +#define XK_Etilde 0x1001ebc /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */ +#define XK_etilde 0x1001ebd /* U+1EBD LATIN SMALL LETTER E WITH TILDE */ +#define XK_Ecircumflexacute 0x1001ebe /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ +#define XK_ecircumflexacute 0x1001ebf /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ +#define XK_Ecircumflexgrave 0x1001ec0 /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ +#define XK_ecircumflexgrave 0x1001ec1 /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ +#define XK_Ecircumflexhook 0x1001ec2 /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_ecircumflexhook 0x1001ec3 /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_Ecircumflextilde 0x1001ec4 /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ +#define XK_ecircumflextilde 0x1001ec5 /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ +#define XK_Ecircumflexbelowdot 0x1001ec6 /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_ecircumflexbelowdot 0x1001ec7 /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_Ihook 0x1001ec8 /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */ +#define XK_ihook 0x1001ec9 /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */ +#define XK_Ibelowdot 0x1001eca /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */ +#define XK_ibelowdot 0x1001ecb /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */ +#define XK_Obelowdot 0x1001ecc /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */ +#define XK_obelowdot 0x1001ecd /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */ +#define XK_Ohook 0x1001ece /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */ +#define XK_ohook 0x1001ecf /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */ +#define XK_Ocircumflexacute 0x1001ed0 /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ +#define XK_ocircumflexacute 0x1001ed1 /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ +#define XK_Ocircumflexgrave 0x1001ed2 /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ +#define XK_ocircumflexgrave 0x1001ed3 /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ +#define XK_Ocircumflexhook 0x1001ed4 /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_ocircumflexhook 0x1001ed5 /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_Ocircumflextilde 0x1001ed6 /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ +#define XK_ocircumflextilde 0x1001ed7 /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ +#define XK_Ocircumflexbelowdot 0x1001ed8 /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_ocircumflexbelowdot 0x1001ed9 /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_Ohornacute 0x1001eda /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ +#define XK_ohornacute 0x1001edb /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */ +#define XK_Ohorngrave 0x1001edc /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ +#define XK_ohorngrave 0x1001edd /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */ +#define XK_Ohornhook 0x1001ede /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ +#define XK_ohornhook 0x1001edf /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ +#define XK_Ohorntilde 0x1001ee0 /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */ +#define XK_ohorntilde 0x1001ee1 /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */ +#define XK_Ohornbelowdot 0x1001ee2 /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ +#define XK_ohornbelowdot 0x1001ee3 /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ +#define XK_Ubelowdot 0x1001ee4 /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */ +#define XK_ubelowdot 0x1001ee5 /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */ +#define XK_Uhook 0x1001ee6 /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */ +#define XK_uhook 0x1001ee7 /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */ +#define XK_Uhornacute 0x1001ee8 /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ +#define XK_uhornacute 0x1001ee9 /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */ +#define XK_Uhorngrave 0x1001eea /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ +#define XK_uhorngrave 0x1001eeb /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */ +#define XK_Uhornhook 0x1001eec /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ +#define XK_uhornhook 0x1001eed /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ +#define XK_Uhorntilde 0x1001eee /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */ +#define XK_uhorntilde 0x1001eef /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */ +#define XK_Uhornbelowdot 0x1001ef0 /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ +#define XK_uhornbelowdot 0x1001ef1 /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ +#define XK_Ybelowdot 0x1001ef4 /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */ +#define XK_ybelowdot 0x1001ef5 /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */ +#define XK_Yhook 0x1001ef6 /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ +#define XK_yhook 0x1001ef7 /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */ +#define XK_Ytilde 0x1001ef8 /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */ +#define XK_ytilde 0x1001ef9 /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */ +#define XK_Ohorn 0x10001a0 /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */ +#define XK_ohorn 0x10001a1 /* U+01A1 LATIN SMALL LETTER O WITH HORN */ +#define XK_Uhorn 0x10001af /* U+01AF LATIN CAPITAL LETTER U WITH HORN */ +#define XK_uhorn 0x10001b0 /* U+01B0 LATIN SMALL LETTER U WITH HORN */ + +#endif /* XK_VIETNAMESE */ + +#ifdef XK_CURRENCY +#define XK_EcuSign 0x10020a0 /* U+20A0 EURO-CURRENCY SIGN */ +#define XK_ColonSign 0x10020a1 /* U+20A1 COLON SIGN */ +#define XK_CruzeiroSign 0x10020a2 /* U+20A2 CRUZEIRO SIGN */ +#define XK_FFrancSign 0x10020a3 /* U+20A3 FRENCH FRANC SIGN */ +#define XK_LiraSign 0x10020a4 /* U+20A4 LIRA SIGN */ +#define XK_MillSign 0x10020a5 /* U+20A5 MILL SIGN */ +#define XK_NairaSign 0x10020a6 /* U+20A6 NAIRA SIGN */ +#define XK_PesetaSign 0x10020a7 /* U+20A7 PESETA SIGN */ +#define XK_RupeeSign 0x10020a8 /* U+20A8 RUPEE SIGN */ +#define XK_WonSign 0x10020a9 /* U+20A9 WON SIGN */ +#define XK_NewSheqelSign 0x10020aa /* U+20AA NEW SHEQEL SIGN */ +#define XK_DongSign 0x10020ab /* U+20AB DONG SIGN */ +#define XK_EuroSign 0x20ac /* U+20AC EURO SIGN */ +#endif /* XK_CURRENCY */ + +#ifdef XK_MATHEMATICAL +/* one, two and three are defined above. */ +#define XK_zerosuperior 0x1002070 /* U+2070 SUPERSCRIPT ZERO */ +#define XK_foursuperior 0x1002074 /* U+2074 SUPERSCRIPT FOUR */ +#define XK_fivesuperior 0x1002075 /* U+2075 SUPERSCRIPT FIVE */ +#define XK_sixsuperior 0x1002076 /* U+2076 SUPERSCRIPT SIX */ +#define XK_sevensuperior 0x1002077 /* U+2077 SUPERSCRIPT SEVEN */ +#define XK_eightsuperior 0x1002078 /* U+2078 SUPERSCRIPT EIGHT */ +#define XK_ninesuperior 0x1002079 /* U+2079 SUPERSCRIPT NINE */ +#define XK_zerosubscript 0x1002080 /* U+2080 SUBSCRIPT ZERO */ +#define XK_onesubscript 0x1002081 /* U+2081 SUBSCRIPT ONE */ +#define XK_twosubscript 0x1002082 /* U+2082 SUBSCRIPT TWO */ +#define XK_threesubscript 0x1002083 /* U+2083 SUBSCRIPT THREE */ +#define XK_foursubscript 0x1002084 /* U+2084 SUBSCRIPT FOUR */ +#define XK_fivesubscript 0x1002085 /* U+2085 SUBSCRIPT FIVE */ +#define XK_sixsubscript 0x1002086 /* U+2086 SUBSCRIPT SIX */ +#define XK_sevensubscript 0x1002087 /* U+2087 SUBSCRIPT SEVEN */ +#define XK_eightsubscript 0x1002088 /* U+2088 SUBSCRIPT EIGHT */ +#define XK_ninesubscript 0x1002089 /* U+2089 SUBSCRIPT NINE */ +#define XK_partdifferential 0x1002202 /* U+2202 PARTIAL DIFFERENTIAL */ +#define XK_emptyset 0x1002205 /* U+2205 NULL SET */ +#define XK_elementof 0x1002208 /* U+2208 ELEMENT OF */ +#define XK_notelementof 0x1002209 /* U+2209 NOT AN ELEMENT OF */ +#define XK_containsas 0x100220B /* U+220B CONTAINS AS MEMBER */ +#define XK_squareroot 0x100221A /* U+221A SQUARE ROOT */ +#define XK_cuberoot 0x100221B /* U+221B CUBE ROOT */ +#define XK_fourthroot 0x100221C /* U+221C FOURTH ROOT */ +#define XK_dintegral 0x100222C /* U+222C DOUBLE INTEGRAL */ +#define XK_tintegral 0x100222D /* U+222D TRIPLE INTEGRAL */ +#define XK_because 0x1002235 /* U+2235 BECAUSE */ +#define XK_approxeq 0x1002248 /* U+2245 ALMOST EQUAL TO */ +#define XK_notapproxeq 0x1002247 /* U+2247 NOT ALMOST EQUAL TO */ +#define XK_notidentical 0x1002262 /* U+2262 NOT IDENTICAL TO */ +#define XK_stricteq 0x1002263 /* U+2263 STRICTLY EQUIVALENT TO */ +#endif /* XK_MATHEMATICAL */ + +#ifdef XK_BRAILLE +#define XK_braille_dot_1 0xfff1 +#define XK_braille_dot_2 0xfff2 +#define XK_braille_dot_3 0xfff3 +#define XK_braille_dot_4 0xfff4 +#define XK_braille_dot_5 0xfff5 +#define XK_braille_dot_6 0xfff6 +#define XK_braille_dot_7 0xfff7 +#define XK_braille_dot_8 0xfff8 +#define XK_braille_dot_9 0xfff9 +#define XK_braille_dot_10 0xfffa +#define XK_braille_blank 0x1002800 /* U+2800 BRAILLE PATTERN BLANK */ +#define XK_braille_dots_1 0x1002801 /* U+2801 BRAILLE PATTERN DOTS-1 */ +#define XK_braille_dots_2 0x1002802 /* U+2802 BRAILLE PATTERN DOTS-2 */ +#define XK_braille_dots_12 0x1002803 /* U+2803 BRAILLE PATTERN DOTS-12 */ +#define XK_braille_dots_3 0x1002804 /* U+2804 BRAILLE PATTERN DOTS-3 */ +#define XK_braille_dots_13 0x1002805 /* U+2805 BRAILLE PATTERN DOTS-13 */ +#define XK_braille_dots_23 0x1002806 /* U+2806 BRAILLE PATTERN DOTS-23 */ +#define XK_braille_dots_123 0x1002807 /* U+2807 BRAILLE PATTERN DOTS-123 */ +#define XK_braille_dots_4 0x1002808 /* U+2808 BRAILLE PATTERN DOTS-4 */ +#define XK_braille_dots_14 0x1002809 /* U+2809 BRAILLE PATTERN DOTS-14 */ +#define XK_braille_dots_24 0x100280a /* U+280a BRAILLE PATTERN DOTS-24 */ +#define XK_braille_dots_124 0x100280b /* U+280b BRAILLE PATTERN DOTS-124 */ +#define XK_braille_dots_34 0x100280c /* U+280c BRAILLE PATTERN DOTS-34 */ +#define XK_braille_dots_134 0x100280d /* U+280d BRAILLE PATTERN DOTS-134 */ +#define XK_braille_dots_234 0x100280e /* U+280e BRAILLE PATTERN DOTS-234 */ +#define XK_braille_dots_1234 0x100280f /* U+280f BRAILLE PATTERN DOTS-1234 */ +#define XK_braille_dots_5 0x1002810 /* U+2810 BRAILLE PATTERN DOTS-5 */ +#define XK_braille_dots_15 0x1002811 /* U+2811 BRAILLE PATTERN DOTS-15 */ +#define XK_braille_dots_25 0x1002812 /* U+2812 BRAILLE PATTERN DOTS-25 */ +#define XK_braille_dots_125 0x1002813 /* U+2813 BRAILLE PATTERN DOTS-125 */ +#define XK_braille_dots_35 0x1002814 /* U+2814 BRAILLE PATTERN DOTS-35 */ +#define XK_braille_dots_135 0x1002815 /* U+2815 BRAILLE PATTERN DOTS-135 */ +#define XK_braille_dots_235 0x1002816 /* U+2816 BRAILLE PATTERN DOTS-235 */ +#define XK_braille_dots_1235 0x1002817 /* U+2817 BRAILLE PATTERN DOTS-1235 */ +#define XK_braille_dots_45 0x1002818 /* U+2818 BRAILLE PATTERN DOTS-45 */ +#define XK_braille_dots_145 0x1002819 /* U+2819 BRAILLE PATTERN DOTS-145 */ +#define XK_braille_dots_245 0x100281a /* U+281a BRAILLE PATTERN DOTS-245 */ +#define XK_braille_dots_1245 0x100281b /* U+281b BRAILLE PATTERN DOTS-1245 */ +#define XK_braille_dots_345 0x100281c /* U+281c BRAILLE PATTERN DOTS-345 */ +#define XK_braille_dots_1345 0x100281d /* U+281d BRAILLE PATTERN DOTS-1345 */ +#define XK_braille_dots_2345 0x100281e /* U+281e BRAILLE PATTERN DOTS-2345 */ +#define XK_braille_dots_12345 0x100281f /* U+281f BRAILLE PATTERN DOTS-12345 */ +#define XK_braille_dots_6 0x1002820 /* U+2820 BRAILLE PATTERN DOTS-6 */ +#define XK_braille_dots_16 0x1002821 /* U+2821 BRAILLE PATTERN DOTS-16 */ +#define XK_braille_dots_26 0x1002822 /* U+2822 BRAILLE PATTERN DOTS-26 */ +#define XK_braille_dots_126 0x1002823 /* U+2823 BRAILLE PATTERN DOTS-126 */ +#define XK_braille_dots_36 0x1002824 /* U+2824 BRAILLE PATTERN DOTS-36 */ +#define XK_braille_dots_136 0x1002825 /* U+2825 BRAILLE PATTERN DOTS-136 */ +#define XK_braille_dots_236 0x1002826 /* U+2826 BRAILLE PATTERN DOTS-236 */ +#define XK_braille_dots_1236 0x1002827 /* U+2827 BRAILLE PATTERN DOTS-1236 */ +#define XK_braille_dots_46 0x1002828 /* U+2828 BRAILLE PATTERN DOTS-46 */ +#define XK_braille_dots_146 0x1002829 /* U+2829 BRAILLE PATTERN DOTS-146 */ +#define XK_braille_dots_246 0x100282a /* U+282a BRAILLE PATTERN DOTS-246 */ +#define XK_braille_dots_1246 0x100282b /* U+282b BRAILLE PATTERN DOTS-1246 */ +#define XK_braille_dots_346 0x100282c /* U+282c BRAILLE PATTERN DOTS-346 */ +#define XK_braille_dots_1346 0x100282d /* U+282d BRAILLE PATTERN DOTS-1346 */ +#define XK_braille_dots_2346 0x100282e /* U+282e BRAILLE PATTERN DOTS-2346 */ +#define XK_braille_dots_12346 0x100282f /* U+282f BRAILLE PATTERN DOTS-12346 */ +#define XK_braille_dots_56 0x1002830 /* U+2830 BRAILLE PATTERN DOTS-56 */ +#define XK_braille_dots_156 0x1002831 /* U+2831 BRAILLE PATTERN DOTS-156 */ +#define XK_braille_dots_256 0x1002832 /* U+2832 BRAILLE PATTERN DOTS-256 */ +#define XK_braille_dots_1256 0x1002833 /* U+2833 BRAILLE PATTERN DOTS-1256 */ +#define XK_braille_dots_356 0x1002834 /* U+2834 BRAILLE PATTERN DOTS-356 */ +#define XK_braille_dots_1356 0x1002835 /* U+2835 BRAILLE PATTERN DOTS-1356 */ +#define XK_braille_dots_2356 0x1002836 /* U+2836 BRAILLE PATTERN DOTS-2356 */ +#define XK_braille_dots_12356 0x1002837 /* U+2837 BRAILLE PATTERN DOTS-12356 */ +#define XK_braille_dots_456 0x1002838 /* U+2838 BRAILLE PATTERN DOTS-456 */ +#define XK_braille_dots_1456 0x1002839 /* U+2839 BRAILLE PATTERN DOTS-1456 */ +#define XK_braille_dots_2456 0x100283a /* U+283a BRAILLE PATTERN DOTS-2456 */ +#define XK_braille_dots_12456 0x100283b /* U+283b BRAILLE PATTERN DOTS-12456 */ +#define XK_braille_dots_3456 0x100283c /* U+283c BRAILLE PATTERN DOTS-3456 */ +#define XK_braille_dots_13456 0x100283d /* U+283d BRAILLE PATTERN DOTS-13456 */ +#define XK_braille_dots_23456 0x100283e /* U+283e BRAILLE PATTERN DOTS-23456 */ +#define XK_braille_dots_123456 0x100283f /* U+283f BRAILLE PATTERN DOTS-123456 */ +#define XK_braille_dots_7 0x1002840 /* U+2840 BRAILLE PATTERN DOTS-7 */ +#define XK_braille_dots_17 0x1002841 /* U+2841 BRAILLE PATTERN DOTS-17 */ +#define XK_braille_dots_27 0x1002842 /* U+2842 BRAILLE PATTERN DOTS-27 */ +#define XK_braille_dots_127 0x1002843 /* U+2843 BRAILLE PATTERN DOTS-127 */ +#define XK_braille_dots_37 0x1002844 /* U+2844 BRAILLE PATTERN DOTS-37 */ +#define XK_braille_dots_137 0x1002845 /* U+2845 BRAILLE PATTERN DOTS-137 */ +#define XK_braille_dots_237 0x1002846 /* U+2846 BRAILLE PATTERN DOTS-237 */ +#define XK_braille_dots_1237 0x1002847 /* U+2847 BRAILLE PATTERN DOTS-1237 */ +#define XK_braille_dots_47 0x1002848 /* U+2848 BRAILLE PATTERN DOTS-47 */ +#define XK_braille_dots_147 0x1002849 /* U+2849 BRAILLE PATTERN DOTS-147 */ +#define XK_braille_dots_247 0x100284a /* U+284a BRAILLE PATTERN DOTS-247 */ +#define XK_braille_dots_1247 0x100284b /* U+284b BRAILLE PATTERN DOTS-1247 */ +#define XK_braille_dots_347 0x100284c /* U+284c BRAILLE PATTERN DOTS-347 */ +#define XK_braille_dots_1347 0x100284d /* U+284d BRAILLE PATTERN DOTS-1347 */ +#define XK_braille_dots_2347 0x100284e /* U+284e BRAILLE PATTERN DOTS-2347 */ +#define XK_braille_dots_12347 0x100284f /* U+284f BRAILLE PATTERN DOTS-12347 */ +#define XK_braille_dots_57 0x1002850 /* U+2850 BRAILLE PATTERN DOTS-57 */ +#define XK_braille_dots_157 0x1002851 /* U+2851 BRAILLE PATTERN DOTS-157 */ +#define XK_braille_dots_257 0x1002852 /* U+2852 BRAILLE PATTERN DOTS-257 */ +#define XK_braille_dots_1257 0x1002853 /* U+2853 BRAILLE PATTERN DOTS-1257 */ +#define XK_braille_dots_357 0x1002854 /* U+2854 BRAILLE PATTERN DOTS-357 */ +#define XK_braille_dots_1357 0x1002855 /* U+2855 BRAILLE PATTERN DOTS-1357 */ +#define XK_braille_dots_2357 0x1002856 /* U+2856 BRAILLE PATTERN DOTS-2357 */ +#define XK_braille_dots_12357 0x1002857 /* U+2857 BRAILLE PATTERN DOTS-12357 */ +#define XK_braille_dots_457 0x1002858 /* U+2858 BRAILLE PATTERN DOTS-457 */ +#define XK_braille_dots_1457 0x1002859 /* U+2859 BRAILLE PATTERN DOTS-1457 */ +#define XK_braille_dots_2457 0x100285a /* U+285a BRAILLE PATTERN DOTS-2457 */ +#define XK_braille_dots_12457 0x100285b /* U+285b BRAILLE PATTERN DOTS-12457 */ +#define XK_braille_dots_3457 0x100285c /* U+285c BRAILLE PATTERN DOTS-3457 */ +#define XK_braille_dots_13457 0x100285d /* U+285d BRAILLE PATTERN DOTS-13457 */ +#define XK_braille_dots_23457 0x100285e /* U+285e BRAILLE PATTERN DOTS-23457 */ +#define XK_braille_dots_123457 0x100285f /* U+285f BRAILLE PATTERN DOTS-123457 */ +#define XK_braille_dots_67 0x1002860 /* U+2860 BRAILLE PATTERN DOTS-67 */ +#define XK_braille_dots_167 0x1002861 /* U+2861 BRAILLE PATTERN DOTS-167 */ +#define XK_braille_dots_267 0x1002862 /* U+2862 BRAILLE PATTERN DOTS-267 */ +#define XK_braille_dots_1267 0x1002863 /* U+2863 BRAILLE PATTERN DOTS-1267 */ +#define XK_braille_dots_367 0x1002864 /* U+2864 BRAILLE PATTERN DOTS-367 */ +#define XK_braille_dots_1367 0x1002865 /* U+2865 BRAILLE PATTERN DOTS-1367 */ +#define XK_braille_dots_2367 0x1002866 /* U+2866 BRAILLE PATTERN DOTS-2367 */ +#define XK_braille_dots_12367 0x1002867 /* U+2867 BRAILLE PATTERN DOTS-12367 */ +#define XK_braille_dots_467 0x1002868 /* U+2868 BRAILLE PATTERN DOTS-467 */ +#define XK_braille_dots_1467 0x1002869 /* U+2869 BRAILLE PATTERN DOTS-1467 */ +#define XK_braille_dots_2467 0x100286a /* U+286a BRAILLE PATTERN DOTS-2467 */ +#define XK_braille_dots_12467 0x100286b /* U+286b BRAILLE PATTERN DOTS-12467 */ +#define XK_braille_dots_3467 0x100286c /* U+286c BRAILLE PATTERN DOTS-3467 */ +#define XK_braille_dots_13467 0x100286d /* U+286d BRAILLE PATTERN DOTS-13467 */ +#define XK_braille_dots_23467 0x100286e /* U+286e BRAILLE PATTERN DOTS-23467 */ +#define XK_braille_dots_123467 0x100286f /* U+286f BRAILLE PATTERN DOTS-123467 */ +#define XK_braille_dots_567 0x1002870 /* U+2870 BRAILLE PATTERN DOTS-567 */ +#define XK_braille_dots_1567 0x1002871 /* U+2871 BRAILLE PATTERN DOTS-1567 */ +#define XK_braille_dots_2567 0x1002872 /* U+2872 BRAILLE PATTERN DOTS-2567 */ +#define XK_braille_dots_12567 0x1002873 /* U+2873 BRAILLE PATTERN DOTS-12567 */ +#define XK_braille_dots_3567 0x1002874 /* U+2874 BRAILLE PATTERN DOTS-3567 */ +#define XK_braille_dots_13567 0x1002875 /* U+2875 BRAILLE PATTERN DOTS-13567 */ +#define XK_braille_dots_23567 0x1002876 /* U+2876 BRAILLE PATTERN DOTS-23567 */ +#define XK_braille_dots_123567 0x1002877 /* U+2877 BRAILLE PATTERN DOTS-123567 */ +#define XK_braille_dots_4567 0x1002878 /* U+2878 BRAILLE PATTERN DOTS-4567 */ +#define XK_braille_dots_14567 0x1002879 /* U+2879 BRAILLE PATTERN DOTS-14567 */ +#define XK_braille_dots_24567 0x100287a /* U+287a BRAILLE PATTERN DOTS-24567 */ +#define XK_braille_dots_124567 0x100287b /* U+287b BRAILLE PATTERN DOTS-124567 */ +#define XK_braille_dots_34567 0x100287c /* U+287c BRAILLE PATTERN DOTS-34567 */ +#define XK_braille_dots_134567 0x100287d /* U+287d BRAILLE PATTERN DOTS-134567 */ +#define XK_braille_dots_234567 0x100287e /* U+287e BRAILLE PATTERN DOTS-234567 */ +#define XK_braille_dots_1234567 0x100287f /* U+287f BRAILLE PATTERN DOTS-1234567 */ +#define XK_braille_dots_8 0x1002880 /* U+2880 BRAILLE PATTERN DOTS-8 */ +#define XK_braille_dots_18 0x1002881 /* U+2881 BRAILLE PATTERN DOTS-18 */ +#define XK_braille_dots_28 0x1002882 /* U+2882 BRAILLE PATTERN DOTS-28 */ +#define XK_braille_dots_128 0x1002883 /* U+2883 BRAILLE PATTERN DOTS-128 */ +#define XK_braille_dots_38 0x1002884 /* U+2884 BRAILLE PATTERN DOTS-38 */ +#define XK_braille_dots_138 0x1002885 /* U+2885 BRAILLE PATTERN DOTS-138 */ +#define XK_braille_dots_238 0x1002886 /* U+2886 BRAILLE PATTERN DOTS-238 */ +#define XK_braille_dots_1238 0x1002887 /* U+2887 BRAILLE PATTERN DOTS-1238 */ +#define XK_braille_dots_48 0x1002888 /* U+2888 BRAILLE PATTERN DOTS-48 */ +#define XK_braille_dots_148 0x1002889 /* U+2889 BRAILLE PATTERN DOTS-148 */ +#define XK_braille_dots_248 0x100288a /* U+288a BRAILLE PATTERN DOTS-248 */ +#define XK_braille_dots_1248 0x100288b /* U+288b BRAILLE PATTERN DOTS-1248 */ +#define XK_braille_dots_348 0x100288c /* U+288c BRAILLE PATTERN DOTS-348 */ +#define XK_braille_dots_1348 0x100288d /* U+288d BRAILLE PATTERN DOTS-1348 */ +#define XK_braille_dots_2348 0x100288e /* U+288e BRAILLE PATTERN DOTS-2348 */ +#define XK_braille_dots_12348 0x100288f /* U+288f BRAILLE PATTERN DOTS-12348 */ +#define XK_braille_dots_58 0x1002890 /* U+2890 BRAILLE PATTERN DOTS-58 */ +#define XK_braille_dots_158 0x1002891 /* U+2891 BRAILLE PATTERN DOTS-158 */ +#define XK_braille_dots_258 0x1002892 /* U+2892 BRAILLE PATTERN DOTS-258 */ +#define XK_braille_dots_1258 0x1002893 /* U+2893 BRAILLE PATTERN DOTS-1258 */ +#define XK_braille_dots_358 0x1002894 /* U+2894 BRAILLE PATTERN DOTS-358 */ +#define XK_braille_dots_1358 0x1002895 /* U+2895 BRAILLE PATTERN DOTS-1358 */ +#define XK_braille_dots_2358 0x1002896 /* U+2896 BRAILLE PATTERN DOTS-2358 */ +#define XK_braille_dots_12358 0x1002897 /* U+2897 BRAILLE PATTERN DOTS-12358 */ +#define XK_braille_dots_458 0x1002898 /* U+2898 BRAILLE PATTERN DOTS-458 */ +#define XK_braille_dots_1458 0x1002899 /* U+2899 BRAILLE PATTERN DOTS-1458 */ +#define XK_braille_dots_2458 0x100289a /* U+289a BRAILLE PATTERN DOTS-2458 */ +#define XK_braille_dots_12458 0x100289b /* U+289b BRAILLE PATTERN DOTS-12458 */ +#define XK_braille_dots_3458 0x100289c /* U+289c BRAILLE PATTERN DOTS-3458 */ +#define XK_braille_dots_13458 0x100289d /* U+289d BRAILLE PATTERN DOTS-13458 */ +#define XK_braille_dots_23458 0x100289e /* U+289e BRAILLE PATTERN DOTS-23458 */ +#define XK_braille_dots_123458 0x100289f /* U+289f BRAILLE PATTERN DOTS-123458 */ +#define XK_braille_dots_68 0x10028a0 /* U+28a0 BRAILLE PATTERN DOTS-68 */ +#define XK_braille_dots_168 0x10028a1 /* U+28a1 BRAILLE PATTERN DOTS-168 */ +#define XK_braille_dots_268 0x10028a2 /* U+28a2 BRAILLE PATTERN DOTS-268 */ +#define XK_braille_dots_1268 0x10028a3 /* U+28a3 BRAILLE PATTERN DOTS-1268 */ +#define XK_braille_dots_368 0x10028a4 /* U+28a4 BRAILLE PATTERN DOTS-368 */ +#define XK_braille_dots_1368 0x10028a5 /* U+28a5 BRAILLE PATTERN DOTS-1368 */ +#define XK_braille_dots_2368 0x10028a6 /* U+28a6 BRAILLE PATTERN DOTS-2368 */ +#define XK_braille_dots_12368 0x10028a7 /* U+28a7 BRAILLE PATTERN DOTS-12368 */ +#define XK_braille_dots_468 0x10028a8 /* U+28a8 BRAILLE PATTERN DOTS-468 */ +#define XK_braille_dots_1468 0x10028a9 /* U+28a9 BRAILLE PATTERN DOTS-1468 */ +#define XK_braille_dots_2468 0x10028aa /* U+28aa BRAILLE PATTERN DOTS-2468 */ +#define XK_braille_dots_12468 0x10028ab /* U+28ab BRAILLE PATTERN DOTS-12468 */ +#define XK_braille_dots_3468 0x10028ac /* U+28ac BRAILLE PATTERN DOTS-3468 */ +#define XK_braille_dots_13468 0x10028ad /* U+28ad BRAILLE PATTERN DOTS-13468 */ +#define XK_braille_dots_23468 0x10028ae /* U+28ae BRAILLE PATTERN DOTS-23468 */ +#define XK_braille_dots_123468 0x10028af /* U+28af BRAILLE PATTERN DOTS-123468 */ +#define XK_braille_dots_568 0x10028b0 /* U+28b0 BRAILLE PATTERN DOTS-568 */ +#define XK_braille_dots_1568 0x10028b1 /* U+28b1 BRAILLE PATTERN DOTS-1568 */ +#define XK_braille_dots_2568 0x10028b2 /* U+28b2 BRAILLE PATTERN DOTS-2568 */ +#define XK_braille_dots_12568 0x10028b3 /* U+28b3 BRAILLE PATTERN DOTS-12568 */ +#define XK_braille_dots_3568 0x10028b4 /* U+28b4 BRAILLE PATTERN DOTS-3568 */ +#define XK_braille_dots_13568 0x10028b5 /* U+28b5 BRAILLE PATTERN DOTS-13568 */ +#define XK_braille_dots_23568 0x10028b6 /* U+28b6 BRAILLE PATTERN DOTS-23568 */ +#define XK_braille_dots_123568 0x10028b7 /* U+28b7 BRAILLE PATTERN DOTS-123568 */ +#define XK_braille_dots_4568 0x10028b8 /* U+28b8 BRAILLE PATTERN DOTS-4568 */ +#define XK_braille_dots_14568 0x10028b9 /* U+28b9 BRAILLE PATTERN DOTS-14568 */ +#define XK_braille_dots_24568 0x10028ba /* U+28ba BRAILLE PATTERN DOTS-24568 */ +#define XK_braille_dots_124568 0x10028bb /* U+28bb BRAILLE PATTERN DOTS-124568 */ +#define XK_braille_dots_34568 0x10028bc /* U+28bc BRAILLE PATTERN DOTS-34568 */ +#define XK_braille_dots_134568 0x10028bd /* U+28bd BRAILLE PATTERN DOTS-134568 */ +#define XK_braille_dots_234568 0x10028be /* U+28be BRAILLE PATTERN DOTS-234568 */ +#define XK_braille_dots_1234568 0x10028bf /* U+28bf BRAILLE PATTERN DOTS-1234568 */ +#define XK_braille_dots_78 0x10028c0 /* U+28c0 BRAILLE PATTERN DOTS-78 */ +#define XK_braille_dots_178 0x10028c1 /* U+28c1 BRAILLE PATTERN DOTS-178 */ +#define XK_braille_dots_278 0x10028c2 /* U+28c2 BRAILLE PATTERN DOTS-278 */ +#define XK_braille_dots_1278 0x10028c3 /* U+28c3 BRAILLE PATTERN DOTS-1278 */ +#define XK_braille_dots_378 0x10028c4 /* U+28c4 BRAILLE PATTERN DOTS-378 */ +#define XK_braille_dots_1378 0x10028c5 /* U+28c5 BRAILLE PATTERN DOTS-1378 */ +#define XK_braille_dots_2378 0x10028c6 /* U+28c6 BRAILLE PATTERN DOTS-2378 */ +#define XK_braille_dots_12378 0x10028c7 /* U+28c7 BRAILLE PATTERN DOTS-12378 */ +#define XK_braille_dots_478 0x10028c8 /* U+28c8 BRAILLE PATTERN DOTS-478 */ +#define XK_braille_dots_1478 0x10028c9 /* U+28c9 BRAILLE PATTERN DOTS-1478 */ +#define XK_braille_dots_2478 0x10028ca /* U+28ca BRAILLE PATTERN DOTS-2478 */ +#define XK_braille_dots_12478 0x10028cb /* U+28cb BRAILLE PATTERN DOTS-12478 */ +#define XK_braille_dots_3478 0x10028cc /* U+28cc BRAILLE PATTERN DOTS-3478 */ +#define XK_braille_dots_13478 0x10028cd /* U+28cd BRAILLE PATTERN DOTS-13478 */ +#define XK_braille_dots_23478 0x10028ce /* U+28ce BRAILLE PATTERN DOTS-23478 */ +#define XK_braille_dots_123478 0x10028cf /* U+28cf BRAILLE PATTERN DOTS-123478 */ +#define XK_braille_dots_578 0x10028d0 /* U+28d0 BRAILLE PATTERN DOTS-578 */ +#define XK_braille_dots_1578 0x10028d1 /* U+28d1 BRAILLE PATTERN DOTS-1578 */ +#define XK_braille_dots_2578 0x10028d2 /* U+28d2 BRAILLE PATTERN DOTS-2578 */ +#define XK_braille_dots_12578 0x10028d3 /* U+28d3 BRAILLE PATTERN DOTS-12578 */ +#define XK_braille_dots_3578 0x10028d4 /* U+28d4 BRAILLE PATTERN DOTS-3578 */ +#define XK_braille_dots_13578 0x10028d5 /* U+28d5 BRAILLE PATTERN DOTS-13578 */ +#define XK_braille_dots_23578 0x10028d6 /* U+28d6 BRAILLE PATTERN DOTS-23578 */ +#define XK_braille_dots_123578 0x10028d7 /* U+28d7 BRAILLE PATTERN DOTS-123578 */ +#define XK_braille_dots_4578 0x10028d8 /* U+28d8 BRAILLE PATTERN DOTS-4578 */ +#define XK_braille_dots_14578 0x10028d9 /* U+28d9 BRAILLE PATTERN DOTS-14578 */ +#define XK_braille_dots_24578 0x10028da /* U+28da BRAILLE PATTERN DOTS-24578 */ +#define XK_braille_dots_124578 0x10028db /* U+28db BRAILLE PATTERN DOTS-124578 */ +#define XK_braille_dots_34578 0x10028dc /* U+28dc BRAILLE PATTERN DOTS-34578 */ +#define XK_braille_dots_134578 0x10028dd /* U+28dd BRAILLE PATTERN DOTS-134578 */ +#define XK_braille_dots_234578 0x10028de /* U+28de BRAILLE PATTERN DOTS-234578 */ +#define XK_braille_dots_1234578 0x10028df /* U+28df BRAILLE PATTERN DOTS-1234578 */ +#define XK_braille_dots_678 0x10028e0 /* U+28e0 BRAILLE PATTERN DOTS-678 */ +#define XK_braille_dots_1678 0x10028e1 /* U+28e1 BRAILLE PATTERN DOTS-1678 */ +#define XK_braille_dots_2678 0x10028e2 /* U+28e2 BRAILLE PATTERN DOTS-2678 */ +#define XK_braille_dots_12678 0x10028e3 /* U+28e3 BRAILLE PATTERN DOTS-12678 */ +#define XK_braille_dots_3678 0x10028e4 /* U+28e4 BRAILLE PATTERN DOTS-3678 */ +#define XK_braille_dots_13678 0x10028e5 /* U+28e5 BRAILLE PATTERN DOTS-13678 */ +#define XK_braille_dots_23678 0x10028e6 /* U+28e6 BRAILLE PATTERN DOTS-23678 */ +#define XK_braille_dots_123678 0x10028e7 /* U+28e7 BRAILLE PATTERN DOTS-123678 */ +#define XK_braille_dots_4678 0x10028e8 /* U+28e8 BRAILLE PATTERN DOTS-4678 */ +#define XK_braille_dots_14678 0x10028e9 /* U+28e9 BRAILLE PATTERN DOTS-14678 */ +#define XK_braille_dots_24678 0x10028ea /* U+28ea BRAILLE PATTERN DOTS-24678 */ +#define XK_braille_dots_124678 0x10028eb /* U+28eb BRAILLE PATTERN DOTS-124678 */ +#define XK_braille_dots_34678 0x10028ec /* U+28ec BRAILLE PATTERN DOTS-34678 */ +#define XK_braille_dots_134678 0x10028ed /* U+28ed BRAILLE PATTERN DOTS-134678 */ +#define XK_braille_dots_234678 0x10028ee /* U+28ee BRAILLE PATTERN DOTS-234678 */ +#define XK_braille_dots_1234678 0x10028ef /* U+28ef BRAILLE PATTERN DOTS-1234678 */ +#define XK_braille_dots_5678 0x10028f0 /* U+28f0 BRAILLE PATTERN DOTS-5678 */ +#define XK_braille_dots_15678 0x10028f1 /* U+28f1 BRAILLE PATTERN DOTS-15678 */ +#define XK_braille_dots_25678 0x10028f2 /* U+28f2 BRAILLE PATTERN DOTS-25678 */ +#define XK_braille_dots_125678 0x10028f3 /* U+28f3 BRAILLE PATTERN DOTS-125678 */ +#define XK_braille_dots_35678 0x10028f4 /* U+28f4 BRAILLE PATTERN DOTS-35678 */ +#define XK_braille_dots_135678 0x10028f5 /* U+28f5 BRAILLE PATTERN DOTS-135678 */ +#define XK_braille_dots_235678 0x10028f6 /* U+28f6 BRAILLE PATTERN DOTS-235678 */ +#define XK_braille_dots_1235678 0x10028f7 /* U+28f7 BRAILLE PATTERN DOTS-1235678 */ +#define XK_braille_dots_45678 0x10028f8 /* U+28f8 BRAILLE PATTERN DOTS-45678 */ +#define XK_braille_dots_145678 0x10028f9 /* U+28f9 BRAILLE PATTERN DOTS-145678 */ +#define XK_braille_dots_245678 0x10028fa /* U+28fa BRAILLE PATTERN DOTS-245678 */ +#define XK_braille_dots_1245678 0x10028fb /* U+28fb BRAILLE PATTERN DOTS-1245678 */ +#define XK_braille_dots_345678 0x10028fc /* U+28fc BRAILLE PATTERN DOTS-345678 */ +#define XK_braille_dots_1345678 0x10028fd /* U+28fd BRAILLE PATTERN DOTS-1345678 */ +#define XK_braille_dots_2345678 0x10028fe /* U+28fe BRAILLE PATTERN DOTS-2345678 */ +#define XK_braille_dots_12345678 0x10028ff /* U+28ff BRAILLE PATTERN DOTS-12345678 */ +#endif /* XK_BRAILLE */ diff --git a/simulators/gem5/src/Doxyfile b/simulators/gem5/src/Doxyfile new file mode 100644 index 00000000..ed4245dd --- /dev/null +++ b/simulators/gem5/src/Doxyfile @@ -0,0 +1,1127 @@ +# Doxyfile 1.3.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = M5 + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doxygen + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = . + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = *.c \ + *.cc \ + *.h \ + *.hh \ + *.doxygen + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = build \ + configs \ + setup \ + PENDING \ + RESYNC + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = */BitKeeper/* \ + */Attic/* \ + */SCCS/* + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 3 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = doxygen/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/simulators/gem5/src/SConscript b/simulators/gem5/src/SConscript new file mode 100755 index 00000000..24d31fcc --- /dev/null +++ b/simulators/gem5/src/SConscript @@ -0,0 +1,1013 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import array +import bisect +import imp +import marshal +import os +import re +import sys +import zlib + +from os.path import basename, dirname, exists, isdir, isfile, join as joinpath + +import SCons + +# This file defines how to build a particular configuration of gem5 +# based on variable settings in the 'env' build environment. + +Import('*') + +# Children need to see the environment +Export('env') + +build_env = [(opt, env[opt]) for opt in export_vars] + +from m5.util import code_formatter, compareVersions + +######################################################################## +# Code for adding source files of various types +# +# When specifying a source file of some type, a set of guards can be +# specified for that file. When get() is used to find the files, if +# get specifies a set of filters, only files that match those filters +# will be accepted (unspecified filters on files are assumed to be +# false). Current filters are: +# main -- specifies the gem5 main() function +# skip_lib -- do not put this file into the gem5 library +# -- unit tests use filters based on the unit test name +# +# A parent can now be specified for a source file and default filter +# values will be retrieved recursively from parents (children override +# parents). +# +class SourceMeta(type): + '''Meta class for source files that keeps track of all files of a + particular type and has a get function for finding all functions + of a certain type that match a set of guards''' + def __init__(cls, name, bases, dict): + super(SourceMeta, cls).__init__(name, bases, dict) + cls.all = [] + + def get(cls, **guards): + '''Find all files that match the specified guards. If a source + file does not specify a flag, the default is False''' + for src in cls.all: + for flag,value in guards.iteritems(): + # if the flag is found and has a different value, skip + # this file + if src.all_guards.get(flag, False) != value: + break + else: + yield src + +class SourceFile(object): + '''Base object that encapsulates the notion of a source file. + This includes, the source node, target node, various manipulations + of those. A source file also specifies a set of guards which + describing which builds the source file applies to. A parent can + also be specified to get default guards from''' + __metaclass__ = SourceMeta + def __init__(self, source, parent=None, **guards): + self.guards = guards + self.parent = parent + + tnode = source + if not isinstance(source, SCons.Node.FS.File): + tnode = File(source) + + self.tnode = tnode + self.snode = tnode.srcnode() + + for base in type(self).__mro__: + if issubclass(base, SourceFile): + base.all.append(self) + + @property + def filename(self): + return str(self.tnode) + + @property + def dirname(self): + return dirname(self.filename) + + @property + def basename(self): + return basename(self.filename) + + @property + def extname(self): + index = self.basename.rfind('.') + if index <= 0: + # dot files aren't extensions + return self.basename, None + + return self.basename[:index], self.basename[index+1:] + + @property + def all_guards(self): + '''find all guards for this object getting default values + recursively from its parents''' + guards = {} + if self.parent: + guards.update(self.parent.guards) + guards.update(self.guards) + return guards + + def __lt__(self, other): return self.filename < other.filename + def __le__(self, other): return self.filename <= other.filename + def __gt__(self, other): return self.filename > other.filename + def __ge__(self, other): return self.filename >= other.filename + def __eq__(self, other): return self.filename == other.filename + def __ne__(self, other): return self.filename != other.filename + +class Source(SourceFile): + '''Add a c/c++ source file to the build''' + def __init__(self, source, Werror=True, swig=False, **guards): + '''specify the source file, and any guards''' + super(Source, self).__init__(source, **guards) + + self.Werror = Werror + self.swig = swig + +class PySource(SourceFile): + '''Add a python source file to the named package''' + invalid_sym_char = re.compile('[^A-z0-9_]') + modules = {} + tnodes = {} + symnames = {} + + def __init__(self, package, source, **guards): + '''specify the python package, the source file, and any guards''' + super(PySource, self).__init__(source, **guards) + + modname,ext = self.extname + assert ext == 'py' + + if package: + path = package.split('.') + else: + path = [] + + modpath = path[:] + if modname != '__init__': + modpath += [ modname ] + modpath = '.'.join(modpath) + + arcpath = path + [ self.basename ] + abspath = self.snode.abspath + if not exists(abspath): + abspath = self.tnode.abspath + + self.package = package + self.modname = modname + self.modpath = modpath + self.arcname = joinpath(*arcpath) + self.abspath = abspath + self.compiled = File(self.filename + 'c') + self.cpp = File(self.filename + '.cc') + self.symname = PySource.invalid_sym_char.sub('_', modpath) + + PySource.modules[modpath] = self + PySource.tnodes[self.tnode] = self + PySource.symnames[self.symname] = self + +class SimObject(PySource): + '''Add a SimObject python file as a python source object and add + it to a list of sim object modules''' + + fixed = False + modnames = [] + + def __init__(self, source, **guards): + '''Specify the source file and any guards (automatically in + the m5.objects package)''' + super(SimObject, self).__init__('m5.objects', source, **guards) + if self.fixed: + raise AttributeError, "Too late to call SimObject now." + + bisect.insort_right(SimObject.modnames, self.modname) + +class SwigSource(SourceFile): + '''Add a swig file to build''' + + def __init__(self, package, source, **guards): + '''Specify the python package, the source file, and any guards''' + super(SwigSource, self).__init__(source, **guards) + + modname,ext = self.extname + assert ext == 'i' + + self.module = modname + cc_file = joinpath(self.dirname, modname + '_wrap.cc') + py_file = joinpath(self.dirname, modname + '.py') + + self.cc_source = Source(cc_file, swig=True, parent=self) + self.py_source = PySource(package, py_file, parent=self) + +class UnitTest(object): + '''Create a UnitTest''' + + all = [] + def __init__(self, target, *sources, **kwargs): + '''Specify the target name and any sources. Sources that are + not SourceFiles are evalued with Source(). All files are + guarded with a guard of the same name as the UnitTest + target.''' + + srcs = [] + for src in sources: + if not isinstance(src, SourceFile): + src = Source(src, skip_lib=True) + src.guards[target] = True + srcs.append(src) + + self.sources = srcs + self.target = target + self.main = kwargs.get('main', False) + UnitTest.all.append(self) + +# Children should have access +Export('Source') +Export('PySource') +Export('SimObject') +Export('SwigSource') +Export('UnitTest') + +######################################################################## +# +# Debug Flags +# +debug_flags = {} +def DebugFlag(name, desc=None): + if name in debug_flags: + raise AttributeError, "Flag %s already specified" % name + debug_flags[name] = (name, (), desc) + +def CompoundFlag(name, flags, desc=None): + if name in debug_flags: + raise AttributeError, "Flag %s already specified" % name + + compound = tuple(flags) + debug_flags[name] = (name, compound, desc) + +Export('DebugFlag') +Export('CompoundFlag') + +######################################################################## +# +# Set some compiler variables +# + +# Include file paths are rooted in this directory. SCons will +# automatically expand '.' to refer to both the source directory and +# the corresponding build directory to pick up generated include +# files. +env.Append(CPPPATH=Dir('.')) + +for extra_dir in extras_dir_list: + env.Append(CPPPATH=Dir(extra_dir)) + +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 gem5 Bug id: 308 +for root, dirs, files in os.walk(base_dir, topdown=True): + Dir(root[len(base_dir) + 1:]) + +######################################################################## +# +# Walk the tree and execute all SConscripts in subdirectories +# + +here = Dir('.').srcnode().abspath +for root, dirs, files in os.walk(base_dir, topdown=True): + if root == here: + # we don't want to recurse back into this SConscript + continue + + if 'SConscript' in files: + build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) + SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) + +for extra_dir in extras_dir_list: + prefix_len = len(dirname(extra_dir)) + 1 + for root, dirs, files in os.walk(extra_dir, topdown=True): + # if build lives in the extras directory, don't walk down it + if 'build' in dirs: + dirs.remove('build') + + if 'SConscript' in files: + build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) + SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) + +for opt in export_vars: + env.ConfigFile(opt) + +def makeTheISA(source, target, env): + isas = [ src.get_contents() for src in source ] + target_isa = env['TARGET_ISA'] + def define(isa): + return isa.upper() + '_ISA' + + def namespace(isa): + return isa[0].upper() + isa[1:].lower() + 'ISA' + + + code = code_formatter() + code('''\ +#ifndef __CONFIG_THE_ISA_HH__ +#define __CONFIG_THE_ISA_HH__ + +''') + + for i,isa in enumerate(isas): + code('#define $0 $1', define(isa), i + 1) + + code(''' + +#define THE_ISA ${{define(target_isa)}} +#define TheISA ${{namespace(target_isa)}} +#define THE_ISA_STR "${{target_isa}}" + +#endif // __CONFIG_THE_ISA_HH__''') + + code.write(str(target[0])) + +env.Command('config/the_isa.hh', map(Value, all_isa_list), + MakeAction(makeTheISA, Transform("CFG ISA", 0))) + +######################################################################## +# +# Prevent any SimObjects from being added after this point, they +# should all have been added in the SConscripts above +# +SimObject.fixed = True + +class DictImporter(object): + '''This importer takes a dictionary of arbitrary module names that + map to arbitrary filenames.''' + def __init__(self, modules): + self.modules = modules + self.installed = set() + + def __del__(self): + self.unload() + + def unload(self): + import sys + for module in self.installed: + del sys.modules[module] + self.installed = set() + + def find_module(self, fullname, path): + if fullname == 'm5.defines': + return self + + if fullname == 'm5.objects': + return self + + if fullname.startswith('m5.internal'): + return None + + source = self.modules.get(fullname, None) + if source is not None and fullname.startswith('m5.objects'): + return self + + return None + + def load_module(self, fullname): + mod = imp.new_module(fullname) + sys.modules[fullname] = mod + self.installed.add(fullname) + + mod.__loader__ = self + if fullname == 'm5.objects': + mod.__path__ = fullname.split('.') + return mod + + if fullname == 'm5.defines': + mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) + return mod + + source = self.modules[fullname] + if source.modname == '__init__': + mod.__path__ = source.modpath + mod.__file__ = source.abspath + + exec file(source.abspath, 'r') in mod.__dict__ + + return mod + +import m5.SimObject +import m5.params +from m5.util import code_formatter + +m5.SimObject.clear() +m5.params.clear() + +# install the python importer so we can grab stuff from the source +# tree itself. We can't have SimObjects added after this point or +# else we won't know about them for the rest of the stuff. +importer = DictImporter(PySource.modules) +sys.meta_path[0:0] = [ importer ] + +# import all sim objects so we can populate the all_objects list +# make sure that we're working with a list, then let's sort it +for modname in SimObject.modnames: + exec('from m5.objects import %s' % modname) + +# we need to unload all of the currently imported modules so that they +# will be re-imported the next time the sconscript is run +importer.unload() +sys.meta_path.remove(importer) + +sim_objects = m5.SimObject.allClasses +all_enums = m5.params.allEnums + +# Find param types that need to be explicitly wrapped with swig. +# These will be recognized because the ParamDesc will have a +# swig_decl() method. Most param types are based on types that don't +# need this, either because they're based on native types (like Int) +# or because they're SimObjects (which get swigged independently). +# For now the only things handled here are VectorParam types. +params_to_swig = {} +for name,obj in sorted(sim_objects.iteritems()): + for param in obj._params.local.values(): + # load the ptype attribute now because it depends on the + # current version of SimObject.allClasses, but when scons + # actually uses the value, all versions of + # SimObject.allClasses will have been loaded + param.ptype + + if not hasattr(param, 'swig_decl'): + continue + pname = param.ptype_str + if pname not in params_to_swig: + params_to_swig[pname] = param + +######################################################################## +# +# calculate extra dependencies +# +module_depends = ["m5", "m5.SimObject", "m5.params"] +depends = [ PySource.modules[dep].snode for dep in module_depends ] + +######################################################################## +# +# Commands for the basic automatically generated python files +# + +# Generate Python file containing a dict specifying the current +# buildEnv flags. +def makeDefinesPyFile(target, source, env): + build_env = source[0].get_contents() + + code = code_formatter() + code(""" +import m5.internal +import m5.util + +buildEnv = m5.util.SmartDict($build_env) + +compileDate = m5.internal.core.compileDate +_globals = globals() +for key,val in m5.internal.core.__dict__.iteritems(): + if key.startswith('flag_'): + flag = key[5:] + _globals[flag] = val +del _globals +""") + code.write(target[0].abspath) + +defines_info = Value(build_env) +# Generate a file with all of the compile options in it +env.Command('python/m5/defines.py', defines_info, + MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) +PySource('m5', 'python/m5/defines.py') + +# Generate python file containing info about the M5 source code +def makeInfoPyFile(target, source, env): + code = code_formatter() + for src in source: + data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) + code('$src = ${{repr(data)}}') + code.write(str(target[0])) + +# Generate a file that wraps the basic top level files +env.Command('python/m5/info.py', + [ '#/COPYING', '#/LICENSE', '#/README', ], + MakeAction(makeInfoPyFile, Transform("INFO"))) +PySource('m5', 'python/m5/info.py') + +######################################################################## +# +# Create all of the SimObject param headers and enum headers +# + +def createSimObjectParamStruct(target, source, env): + assert len(target) == 1 and len(source) == 1 + + name = str(source[0].get_contents()) + obj = sim_objects[name] + + code = code_formatter() + obj.cxx_param_decl(code) + code.write(target[0].abspath) + +def createParamSwigWrapper(target, source, env): + assert len(target) == 1 and len(source) == 1 + + name = str(source[0].get_contents()) + param = params_to_swig[name] + + code = code_formatter() + param.swig_decl(code) + code.write(target[0].abspath) + +def createEnumStrings(target, source, env): + assert len(target) == 1 and len(source) == 1 + + name = str(source[0].get_contents()) + obj = all_enums[name] + + code = code_formatter() + obj.cxx_def(code) + code.write(target[0].abspath) + +def createEnumDecls(target, source, env): + assert len(target) == 1 and len(source) == 1 + + name = str(source[0].get_contents()) + obj = all_enums[name] + + code = code_formatter() + obj.cxx_decl(code) + code.write(target[0].abspath) + +def createEnumSwigWrapper(target, source, env): + assert len(target) == 1 and len(source) == 1 + + name = str(source[0].get_contents()) + obj = all_enums[name] + + code = code_formatter() + obj.swig_decl(code) + code.write(target[0].abspath) + +def createSimObjectSwigWrapper(target, source, env): + name = source[0].get_contents() + obj = sim_objects[name] + + code = code_formatter() + obj.swig_decl(code) + code.write(target[0].abspath) + +# Generate all of the SimObject param C++ struct header files +params_hh_files = [] +for name,simobj in sorted(sim_objects.iteritems()): + py_source = PySource.modules[simobj.__module__] + extra_deps = [ py_source.tnode ] + + hh_file = File('params/%s.hh' % name) + params_hh_files.append(hh_file) + env.Command(hh_file, Value(name), + MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) + env.Depends(hh_file, depends + extra_deps) + +# Generate any needed param SWIG wrapper files +params_i_files = [] +for name,param in params_to_swig.iteritems(): + i_file = File('python/m5/internal/%s.i' % (param.swig_module_name())) + params_i_files.append(i_file) + env.Command(i_file, Value(name), + MakeAction(createParamSwigWrapper, Transform("SW PARAM"))) + env.Depends(i_file, depends) + SwigSource('m5.internal', i_file) + +# Generate all enum header files +for name,enum in sorted(all_enums.iteritems()): + py_source = PySource.modules[enum.__module__] + extra_deps = [ py_source.tnode ] + + cc_file = File('enums/%s.cc' % name) + env.Command(cc_file, Value(name), + MakeAction(createEnumStrings, Transform("ENUM STR"))) + env.Depends(cc_file, depends + extra_deps) + Source(cc_file) + + hh_file = File('enums/%s.hh' % name) + env.Command(hh_file, Value(name), + MakeAction(createEnumDecls, Transform("ENUMDECL"))) + env.Depends(hh_file, depends + extra_deps) + + i_file = File('python/m5/internal/enum_%s.i' % name) + env.Command(i_file, Value(name), + MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG"))) + env.Depends(i_file, depends + extra_deps) + SwigSource('m5.internal', i_file) + +# Generate SimObject SWIG wrapper files +for name in sim_objects.iterkeys(): + i_file = File('python/m5/internal/param_%s.i' % name) + env.Command(i_file, Value(name), + MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG"))) + env.Depends(i_file, depends) + SwigSource('m5.internal', i_file) + +# Generate the main swig init file +def makeEmbeddedSwigInit(target, source, env): + code = code_formatter() + module = source[0].get_contents() + code('''\ +#include "sim/init.hh" + +extern "C" { + void init_${module}(); +} + +EmbeddedSwig embed_swig_${module}(init_${module}); +''') + code.write(str(target[0])) + +# Build all swig modules +for swig in SwigSource.all: + env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, + MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' + '-o ${TARGETS[0]} $SOURCES', Transform("SWIG"))) + cc_file = str(swig.tnode) + init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file)) + env.Command(init_file, Value(swig.module), + MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW"))) + Source(init_file, **swig.guards) + +# +# Handle debug flags +# +def makeDebugFlagCC(target, source, env): + assert(len(target) == 1 and len(source) == 1) + + val = eval(source[0].get_contents()) + name, compound, desc = val + compound = list(sorted(compound)) + + code = code_formatter() + + # file header + code(''' +/* + * DO NOT EDIT THIS FILE! Automatically generated + */ + +#include "base/debug.hh" +''') + + for flag in compound: + code('#include "debug/$flag.hh"') + code() + code('namespace Debug {') + code() + + if not compound: + code('SimpleFlag $name("$name", "$desc");') + else: + code('CompoundFlag $name("$name", "$desc",') + code.indent() + last = len(compound) - 1 + for i,flag in enumerate(compound): + if i != last: + code('$flag,') + else: + code('$flag);') + code.dedent() + + code() + code('} // namespace Debug') + + code.write(str(target[0])) + +def makeDebugFlagHH(target, source, env): + assert(len(target) == 1 and len(source) == 1) + + val = eval(source[0].get_contents()) + name, compound, desc = val + + code = code_formatter() + + # file header boilerplate + code('''\ +/* + * DO NOT EDIT THIS FILE! + * + * Automatically generated by SCons + */ + +#ifndef __DEBUG_${name}_HH__ +#define __DEBUG_${name}_HH__ + +namespace Debug { +''') + + if compound: + code('class CompoundFlag;') + code('class SimpleFlag;') + + if compound: + code('extern CompoundFlag $name;') + for flag in compound: + code('extern SimpleFlag $flag;') + else: + code('extern SimpleFlag $name;') + + code(''' +} + +#endif // __DEBUG_${name}_HH__ +''') + + code.write(str(target[0])) + +for name,flag in sorted(debug_flags.iteritems()): + n, compound, desc = flag + assert n == name + + env.Command('debug/%s.hh' % name, Value(flag), + MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) + env.Command('debug/%s.cc' % name, Value(flag), + MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) + Source('debug/%s.cc' % name) + +# Embed python files. All .py files that have been indicated by a +# PySource() call in a SConscript need to be embedded into the M5 +# library. To do that, we compile the file to byte code, marshal the +# byte code, compress it, and then generate a c++ file that +# inserts the result into an array. +def embedPyFile(target, source, env): + def c_str(string): + if string is None: + return "0" + return '"%s"' % string + + '''Action function to compile a .py into a code object, marshal + it, compress it, and stick it into an asm file so the code appears + as just bytes with a label in the data section''' + + src = file(str(source[0]), 'r').read() + + pysource = PySource.tnodes[source[0]] + compiled = compile(src, pysource.abspath, 'exec') + marshalled = marshal.dumps(compiled) + compressed = zlib.compress(marshalled) + data = compressed + sym = pysource.symname + + code = code_formatter() + code('''\ +#include "sim/init.hh" + +namespace { + +const uint8_t data_${sym}[] = { +''') + code.indent() + step = 16 + for i in xrange(0, len(data), step): + x = array.array('B', data[i:i+step]) + code(''.join('%d,' % d for d in x)) + code.dedent() + + code('''}; + +EmbeddedPython embedded_${sym}( + ${{c_str(pysource.arcname)}}, + ${{c_str(pysource.abspath)}}, + ${{c_str(pysource.modpath)}}, + data_${sym}, + ${{len(data)}}, + ${{len(marshalled)}}); + +} // anonymous namespace +''') + code.write(str(target[0])) + +for source in PySource.all: + env.Command(source.cpp, source.tnode, + MakeAction(embedPyFile, Transform("EMBED PY"))) + Source(source.cpp) + +######################################################################## +# +# Define binaries. Each different build type (debug, opt, etc.) gets +# a slightly different build environment. +# + +# List of constructed environments to pass back to SConstruct +envList = [] + +date_source = Source('base/date.cc', skip_lib=True) + +# Function to create a new build environment as clone of current +# environment 'env' with modified object suffix and optional stripped +# binary. Additional keyword arguments are appended to corresponding +# build environment vars. +def makeEnv(label, objsfx, strip = False, **kwargs): + # SCons doesn't know to append a library suffix when there is a '.' in the + # name. Use '_' instead. + libname = 'gem5_' + label + exename = 'gem5.' + label + secondary_exename = 'm5.' + label + + new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') + new_env.Label = label + new_env.Append(**kwargs) + + swig_env = new_env.Clone() + swig_env.Append(CCFLAGS='-Werror') + if env['GCC']: + swig_env.Append(CCFLAGS='-Wno-uninitialized') + swig_env.Append(CCFLAGS='-Wno-sign-compare') + swig_env.Append(CCFLAGS='-Wno-parentheses') + swig_env.Append(CCFLAGS='-Wno-unused-label') + if compareVersions(env['GCC_VERSION'], '4.6') >= 0: + swig_env.Append(CCFLAGS='-Wno-unused-but-set-variable') + if env['CLANG']: + swig_env.Append(CCFLAGS=['-Wno-unused-label']) + + + werror_env = new_env.Clone() + werror_env.Append(CCFLAGS='-Werror') + + def make_obj(source, static, extra_deps = None): + '''This function adds the specified source to the correct + build environment, and returns the corresponding SCons Object + nodes''' + + if source.swig: + env = swig_env + elif source.Werror: + env = werror_env + else: + env = new_env + + if static: + obj = env.StaticObject(source.tnode) + else: + obj = env.SharedObject(source.tnode) + + if extra_deps: + env.Depends(obj, extra_deps) + + return obj + + static_objs = \ + [ make_obj(s, True) for s in Source.get(main=False, skip_lib=False) ] + shared_objs = \ + [ make_obj(s, False) for s in Source.get(main=False, skip_lib=False) ] + + static_date = make_obj(date_source, static=True, extra_deps=static_objs) + static_objs.append(static_date) + + shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) + shared_objs.append(shared_date) + + # First make a library of everything but main() so other programs can + # link against m5. + static_lib = new_env.StaticLibrary(libname, static_objs) + shared_lib = new_env.SharedLibrary(libname, shared_objs) + + # Now link a stub with main() and the static library. + main_objs = [ make_obj(s, True) for s in Source.get(main=True) ] + + for test in UnitTest.all: + flags = { test.target : True } + test_sources = Source.get(**flags) + test_objs = [ make_obj(s, static=True) for s in test_sources ] + if test.main: + test_objs += main_objs + testname = "unittest/%s.%s" % (test.target, label) + new_env.Program(testname, test_objs + static_objs) + + progname = exename + if strip: + progname += '.unstripped' + + targets = new_env.Program(progname, main_objs + static_objs) + + if strip: + if sys.platform == 'sunos5': + cmd = 'cp $SOURCE $TARGET; strip $TARGET' + else: + cmd = 'strip $SOURCE -o $TARGET' + targets = new_env.Command(exename, progname, + MakeAction(cmd, Transform("STRIP"))) + + new_env.Command(secondary_exename, exename, + MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) + + new_env.M5Binary = targets[0] + envList.append(new_env) + +# Debug binary +ccflags = {} +if env['GCC']: + if sys.platform == 'sunos5': + ccflags['debug'] = '-gstabs+' + else: + ccflags['debug'] = '-ggdb3' + ccflags['opt'] = '-g -O3' + ccflags['fast'] = '-O3' + ccflags['prof'] = '-O3 -g -pg' +elif env['SUNCC']: + ccflags['debug'] = '-g0' + ccflags['opt'] = '-g -O' + ccflags['fast'] = '-fast' + ccflags['prof'] = '-fast -g -pg' +elif env['ICC']: + ccflags['debug'] = '-g -O0' + ccflags['opt'] = '-g -O' + ccflags['fast'] = '-fast' + ccflags['prof'] = '-fast -g -pg' +elif env['CLANG']: + ccflags['debug'] = '-g -O0' + ccflags['opt'] = '-g -O3' + ccflags['fast'] = '-O3' + ccflags['prof'] = '-O3 -g -pg' +else: + print 'Unknown compiler, please fix compiler options' + Exit(1) + + +# To speed things up, we only instantiate the build environments we +# need. We try to identify the needed environment for each target; if +# we can't, we fall back on instantiating all the environments just to +# be safe. +target_types = ['debug', 'opt', 'fast', 'prof'] +obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof'} + +def identifyTarget(t): + ext = t.split('.')[-1] + if ext in target_types: + return ext + if obj2target.has_key(ext): + return obj2target[ext] + match = re.search(r'/tests/([^/]+)/', t) + if match and match.group(1) in target_types: + return match.group(1) + return 'all' + +needed_envs = [identifyTarget(target) for target in BUILD_TARGETS] +if 'all' in needed_envs: + needed_envs += target_types + +# Debug binary +if 'debug' in needed_envs: + makeEnv('debug', '.do', + CCFLAGS = Split(ccflags['debug']), + CPPDEFINES = ['DEBUG', 'TRACING_ON=1']) + +# Optimized binary +if 'opt' in needed_envs: + makeEnv('opt', '.o', + CCFLAGS = Split(ccflags['opt']), + CPPDEFINES = ['TRACING_ON=1']) + +# "Fast" binary +if 'fast' in needed_envs: + makeEnv('fast', '.fo', strip = True, + CCFLAGS = Split(ccflags['fast']), + CPPDEFINES = ['NDEBUG', 'TRACING_ON=0']) + +# Profiled binary +if 'prof' in needed_envs: + makeEnv('prof', '.po', + CCFLAGS = Split(ccflags['prof']), + CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], + LINKFLAGS = '-pg') + +Return('envList') diff --git a/simulators/gem5/src/arch/SConscript b/simulators/gem5/src/arch/SConscript new file mode 100644 index 00000000..b4f94a65 --- /dev/null +++ b/simulators/gem5/src/arch/SConscript @@ -0,0 +1,139 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt + +import sys +import os + +Import('*') + +################################################################# +# +# ISA "switch header" generation. +# +# Auto-generate arch headers that include the right ISA-specific +# header based on the setting of THE_ISA preprocessor variable. +# +################################################################# + +# List of headers to generate +isa_switch_hdrs = Split(''' + decoder.hh + interrupts.hh + isa.hh + isa_traits.hh + kernel_stats.hh + locked_mem.hh + microcode_rom.hh + mmapped_ipr.hh + mt.hh + process.hh + registers.hh + remote_gdb.hh + stacktrace.hh + tlb.hh + types.hh + utility.hh + vtophys.hh + ''') + +# Set up this directory to support switching headers +make_switching_dir('arch', isa_switch_hdrs, env) + +################################################################# +# +# Include architecture-specific files. +# +################################################################# + +# +# Build a SCons scanner for ISA files +# +import SCons.Scanner + +isa_scanner = SCons.Scanner.Classic("ISAScan", + [".isa", ".ISA"], + "SRCDIR", + r'^\s*##include\s+"([\w/.-]*)"') + +env.Append(SCANNERS = isa_scanner) + +# +# Now create a Builder object that uses isa_parser.py to generate C++ +# output from the ISA description (*.isa) files. +# + +isa_parser = File('isa_parser.py') + +# The emitter patches up the sources & targets to include the +# autogenerated files as targets and isa parser itself as a source. +def isa_desc_emitter(target, source, env): + cpu_models = list(env['CPU_MODELS']) + cpu_models.append('CheckerCPU') + + # Several files are generated from the ISA description. + # We always get the basic decoder and header file. + target = [ 'decoder.cc', 'decoder.hh', 'max_inst_regs.hh' ] + # We also get an execute file for each selected CPU model. + target += [CpuModel.dict[cpu].filename for cpu in cpu_models] + + # List the isa parser as a source. + source += [ isa_parser ] + # Add in the CPU models. + source += [ Value(m) for m in cpu_models ] + + return [os.path.join("generated", t) for t in target], source + +ARCH_DIR = Dir('.') + +# import ply here because SCons screws with sys.path when performing actions. +import ply + +def isa_desc_action_func(target, source, env): + # Add the current directory to the system path so we can import files + sys.path[0:0] = [ ARCH_DIR.srcnode().abspath ] + import isa_parser + + # Skip over the ISA description itself and the parser to the CPU models. + models = [ s.get_contents() for s in source[2:] ] + cpu_models = [CpuModel.dict[cpu] for cpu in models] + parser = isa_parser.ISAParser(target[0].dir.abspath, cpu_models) + parser.parse_isa_desc(source[0].abspath) +isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1)) + +# Also include the CheckerCPU as one of the models if it is being +# enabled via command line. +isa_desc_builder = Builder(action=isa_desc_action, emitter=isa_desc_emitter) + +env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) + +DebugFlag('IntRegs') +DebugFlag('FloatRegs') +DebugFlag('MiscRegs') +CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'MiscRegs' ]) diff --git a/simulators/gem5/src/arch/alpha/AlphaInterrupts.py b/simulators/gem5/src/arch/alpha/AlphaInterrupts.py new file mode 100644 index 00000000..ecfcf5c2 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/AlphaInterrupts.py @@ -0,0 +1,33 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject + +class AlphaInterrupts(SimObject): + type = 'AlphaInterrupts' + cxx_class = 'AlphaISA::Interrupts' diff --git a/simulators/gem5/src/arch/alpha/AlphaSystem.py b/simulators/gem5/src/arch/alpha/AlphaSystem.py new file mode 100644 index 00000000..fcbe81ed --- /dev/null +++ b/simulators/gem5/src/arch/alpha/AlphaSystem.py @@ -0,0 +1,57 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.params import * +from m5.proxy import * +from System import System + +class AlphaSystem(System): + type = 'AlphaSystem' + console = Param.String("file that contains the console code") + pal = Param.String("file that contains palcode") + system_type = Param.UInt64("Type of system we are emulating") + system_rev = Param.UInt64("Revision of system we are emulating") + load_addr_mask = 0xffffffffff + +class LinuxAlphaSystem(AlphaSystem): + type = 'LinuxAlphaSystem' + system_type = 34 + system_rev = 1 << 10 + + boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, + "boot processor frequency") + +class FreebsdAlphaSystem(AlphaSystem): + type = 'FreebsdAlphaSystem' + system_type = 34 + system_rev = 1 << 10 + +class Tru64AlphaSystem(AlphaSystem): + type = 'Tru64AlphaSystem' + system_type = 12 + system_rev = 2<<1 diff --git a/simulators/gem5/src/arch/alpha/AlphaTLB.py b/simulators/gem5/src/arch/alpha/AlphaTLB.py new file mode 100644 index 00000000..51f636ec --- /dev/null +++ b/simulators/gem5/src/arch/alpha/AlphaTLB.py @@ -0,0 +1,43 @@ +# Copyright (c) 2005-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.SimObject import SimObject +from m5.params import * + +from BaseTLB import BaseTLB + +class AlphaTLB(BaseTLB): + type = 'AlphaTLB' + cxx_class = 'AlphaISA::TLB' + size = Param.Int("TLB size") + +class AlphaDTB(AlphaTLB): + size = 64 + +class AlphaITB(AlphaTLB): + size = 48 diff --git a/simulators/gem5/src/arch/alpha/SConscript b/simulators/gem5/src/arch/alpha/SConscript new file mode 100644 index 00000000..421040bb --- /dev/null +++ b/simulators/gem5/src/arch/alpha/SConscript @@ -0,0 +1,71 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black +# Steve Reinhardt + +Import('*') + +if env['TARGET_ISA'] == 'alpha': + Source('decoder.cc') + Source('ev5.cc') + Source('faults.cc') + Source('freebsd/system.cc') + Source('idle_event.cc') + Source('interrupts.cc') + Source('ipr.cc') + Source('isa.cc') + Source('kernel_stats.cc') + Source('linux/linux.cc') + Source('linux/process.cc') + Source('linux/system.cc') + Source('osfpal.cc') + Source('pagetable.cc') + Source('process.cc') + Source('regredir.cc') + Source('remote_gdb.cc') + Source('stacktrace.cc') + Source('system.cc') + Source('tlb.cc') + Source('tru64/process.cc') + Source('tru64/system.cc') + Source('tru64/tru64.cc') + Source('utility.cc') + Source('vtophys.cc') + + SimObject('AlphaInterrupts.py') + SimObject('AlphaSystem.py') + SimObject('AlphaTLB.py') + + + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) diff --git a/simulators/gem5/src/arch/alpha/SConsopts b/simulators/gem5/src/arch/alpha/SConsopts new file mode 100644 index 00000000..4af7a4da --- /dev/null +++ b/simulators/gem5/src/arch/alpha/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_isa_list.append('alpha') diff --git a/simulators/gem5/src/arch/alpha/aout_machdep.h b/simulators/gem5/src/arch/alpha/aout_machdep.h new file mode 100644 index 00000000..bcf004d0 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/aout_machdep.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Nathan Binkert + */ + +#ifndef __AOUT_MACHDEP_H__ +#define __AOUT_MACHDEP_H__ + +/// +/// Funky Alpha 64-bit a.out header used for PAL code. +/// +struct aout_exechdr { + uint16_t magic; ///< magic number + uint16_t vstamp; ///< version stamp? + uint16_t bldrev; ///< ??? + uint16_t padcell; ///< padding + uint64_t tsize; ///< text segment size + uint64_t dsize; ///< data segment size + uint64_t bsize; ///< bss segment size + uint64_t entry; ///< entry point + uint64_t text_start; ///< text base address + uint64_t data_start; ///< data base address + uint64_t bss_start; ///< bss base address + uint32_t gprmask; ///< GPR mask (unused, AFAIK) + uint32_t fprmask; ///< FPR mask (unused, AFAIK) + uint64_t gp_value; ///< global pointer reg value +}; + +#define AOUT_LDPGSZ 8192 + +#define N_GETMAGIC(ex) ((ex).magic) + +#define N_BADMAX + +#define N_TXTADDR(ex) ((ex).text_start) +#define N_DATADDR(ex) ((ex).data_start) +#define N_BSSADDR(ex) ((ex).bss_start) + +#define N_TXTOFF(ex) \ + (N_GETMAGIC(ex) == ZMAGIC ? 0 : sizeof(struct aout_exechdr)) + +#define N_DATOFF(ex) N_ALIGN(ex, N_TXTOFF(ex) + (ex).tsize) + +#endif /* !__AOUT_MACHDEP_H__*/ diff --git a/simulators/gem5/src/arch/alpha/decoder.cc b/simulators/gem5/src/arch/alpha/decoder.cc new file mode 100644 index 00000000..e5a7663f --- /dev/null +++ b/simulators/gem5/src/arch/alpha/decoder.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Google + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/alpha/decoder.hh" + +namespace AlphaISA +{ + +GenericISA::BasicDecodeCache Decoder::defaultCache; + +} diff --git a/simulators/gem5/src/arch/alpha/decoder.hh b/simulators/gem5/src/arch/alpha/decoder.hh new file mode 100644 index 00000000..ef2f5856 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/decoder.hh @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2012 Google + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ALPHA_DECODER_HH__ +#define __ARCH_ALPHA_DECODER_HH__ + +#include "arch/generic/decode_cache.hh" +#include "arch/types.hh" +#include "cpu/static_inst.hh" +#include "sim/full_system.hh" + +class ThreadContext; + +namespace AlphaISA +{ + +class Decoder +{ + protected: + ThreadContext *tc; + + // The extended machine instruction being generated + ExtMachInst ext_inst; + bool instDone; + + public: + Decoder(ThreadContext * _tc) : tc(_tc), instDone(false) + {} + + ThreadContext * + getTC() + { + return tc; + } + + void + setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void + process() + { } + + void + reset() + { + instDone = false; + } + + // Use this to give data to the predecoder. This should be used + // when there is control flow. + void + moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) + { + ext_inst = inst; + instDone = true; + if (FullSystem) + ext_inst |= (static_cast(pc.pc() & 0x1) << 32); + } + + bool + needMoreBytes() + { + return true; + } + + bool + instReady() + { + return instDone; + } + + protected: + /// A cache of decoded instruction objects. + static GenericISA::BasicDecodeCache defaultCache; + + public: + StaticInstPtr decodeInst(ExtMachInst mach_inst); + + /// Decode a machine instruction. + /// @param mach_inst The binary instruction to decode. + /// @retval A pointer to the corresponding StaticInst object. + StaticInstPtr + decode(ExtMachInst mach_inst, Addr addr) + { + return defaultCache.decode(this, mach_inst, addr); + } + + StaticInstPtr + decode(AlphaISA::PCState &nextPC) + { + if (!instDone) + return NULL; + instDone = false; + return decode(ext_inst, nextPC.instAddr()); + } +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_DECODER_HH__ diff --git a/simulators/gem5/src/arch/alpha/ecoff_machdep.h b/simulators/gem5/src/arch/alpha/ecoff_machdep.h new file mode 100644 index 00000000..9341b8ff --- /dev/null +++ b/simulators/gem5/src/arch/alpha/ecoff_machdep.h @@ -0,0 +1,73 @@ +/* + * Taken from NetBSD arch/alpha/ecoff_machdep.h + */ + +/* $NetBSD: ecoff_machdep.h,v 1.5 1999/04/27 02:32:33 cgd Exp $ */ + +/* + * Copyright (c) 1994 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the Author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Adam Glass BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// +// Define COFF/ECOFF integer type sizes +// +typedef int16_t coff_short; +typedef uint16_t coff_ushort; +typedef int32_t coff_int; +typedef uint32_t coff_uint; +typedef int64_t coff_long; +typedef uint64_t coff_ulong; +typedef uint64_t coff_addr; + +#define ECOFF_LDPGSZ 4096 + +#define ECOFF_PAD \ + coff_ushort bldrev; /* XXX */ + +#define ECOFF_MACHDEP \ + coff_uint gprmask; \ + coff_uint fprmask; \ + coff_ulong gp_value + +#define ECOFF_MAGIC_ALPHA 0603 +#define ECOFF_MAGIC_NETBSD_ALPHA 0605 +#define ECOFF_BADMAG(ep) \ + ((ep)->f.f_magic != ECOFF_MAGIC_ALPHA && \ + (ep)->f.f_magic != ECOFF_MAGIC_NETBSD_ALPHA) + +#define ECOFF_FLAG_EXEC 0002 +#define ECOFF_SEGMENT_ALIGNMENT(ep) \ + (((ep)->f.f_flags & ECOFF_FLAG_EXEC) == 0 ? 8 : 16) + +#define ECOFF_FLAG_OBJECT_TYPE_MASK 0x3000 +#define ECOFF_OBJECT_TYPE_NO_SHARED 0x1000 +#define ECOFF_OBJECT_TYPE_SHARABLE 0x2000 +#define ECOFF_OBJECT_TYPE_CALL_SHARED 0x3000 + diff --git a/simulators/gem5/src/arch/alpha/ev5.cc b/simulators/gem5/src/arch/alpha/ev5.cc new file mode 100644 index 00000000..4dcc58ff --- /dev/null +++ b/simulators/gem5/src/arch/alpha/ev5.cc @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Nathan Binkert + */ + +#include "arch/alpha/faults.hh" +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/kernel_stats.hh" +#include "arch/alpha/osfpal.hh" +#include "arch/alpha/tlb.hh" +#include "base/cp_annotate.hh" +#include "base/debug.hh" +#include "cpu/base.hh" +#include "cpu/simple_thread.hh" +#include "cpu/thread_context.hh" +#include "sim/sim_exit.hh" + +namespace AlphaISA { + +//////////////////////////////////////////////////////////////////////// +// +// Machine dependent functions +// +void +initCPU(ThreadContext *tc, int cpuId) +{ + initIPRs(tc, cpuId); + + tc->setIntReg(16, cpuId); + tc->setIntReg(0, cpuId); + + AlphaFault *reset = new ResetFault; + + tc->pcState(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); + + delete reset; +} + +template +void +zeroRegisters(CPU *cpu) +{ + // Insure ISA semantics + // (no longer very clean due to the change in setIntReg() in the + // cpu model. Consider changing later.) + cpu->thread->setIntReg(ZeroReg, 0); + cpu->thread->setFloatReg(ZeroReg, 0.0); +} + +//////////////////////////////////////////////////////////////////////// +// +// +// +void +initIPRs(ThreadContext *tc, int cpuId) +{ + for (int i = 0; i < NumInternalProcRegs; ++i) { + tc->setMiscRegNoEffect(i, 0); + } + + tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase); + tc->setMiscRegNoEffect(IPR_MCSR, 0x6); + tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); +} + +MiscReg +ISA::readIpr(int idx, ThreadContext *tc) +{ + uint64_t retval = 0; // return value, default 0 + + switch (idx) { + case IPR_PALtemp0: + case IPR_PALtemp1: + case IPR_PALtemp2: + case IPR_PALtemp3: + case IPR_PALtemp4: + case IPR_PALtemp5: + case IPR_PALtemp6: + case IPR_PALtemp7: + case IPR_PALtemp8: + case IPR_PALtemp9: + case IPR_PALtemp10: + case IPR_PALtemp11: + case IPR_PALtemp12: + case IPR_PALtemp13: + case IPR_PALtemp14: + case IPR_PALtemp15: + case IPR_PALtemp16: + case IPR_PALtemp17: + case IPR_PALtemp18: + case IPR_PALtemp19: + case IPR_PALtemp20: + case IPR_PALtemp21: + case IPR_PALtemp22: + case IPR_PALtemp23: + case IPR_PAL_BASE: + + case IPR_IVPTBR: + case IPR_DC_MODE: + case IPR_MAF_MODE: + case IPR_ISR: + case IPR_EXC_ADDR: + case IPR_IC_PERR_STAT: + case IPR_DC_PERR_STAT: + case IPR_MCSR: + case IPR_ASTRR: + case IPR_ASTER: + case IPR_SIRR: + case IPR_ICSR: + case IPR_ICM: + case IPR_DTB_CM: + case IPR_IPLR: + case IPR_INTID: + case IPR_PMCTR: + // no side-effect + retval = ipr[idx]; + break; + + case IPR_CC: + retval |= ipr[idx] & ULL(0xffffffff00000000); + retval |= tc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff); + break; + + case IPR_VA: + retval = ipr[idx]; + break; + + case IPR_VA_FORM: + case IPR_MM_STAT: + case IPR_IFAULT_VA_FORM: + case IPR_EXC_MASK: + case IPR_EXC_SUM: + retval = ipr[idx]; + break; + + case IPR_DTB_PTE: + { + TlbEntry &entry + = tc->getDTBPtr()->index(!tc->misspeculating()); + + retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32; + retval |= ((uint64_t)entry.xre & ULL(0xf)) << 8; + retval |= ((uint64_t)entry.xwe & ULL(0xf)) << 12; + retval |= ((uint64_t)entry.fonr & ULL(0x1)) << 1; + retval |= ((uint64_t)entry.fonw & ULL(0x1))<< 2; + retval |= ((uint64_t)entry.asma & ULL(0x1)) << 4; + retval |= ((uint64_t)entry.asn & ULL(0x7f)) << 57; + } + break; + + // write only registers + case IPR_HWINT_CLR: + case IPR_SL_XMIT: + case IPR_DC_FLUSH: + case IPR_IC_FLUSH: + case IPR_ALT_MODE: + case IPR_DTB_IA: + case IPR_DTB_IAP: + case IPR_ITB_IA: + case IPR_ITB_IAP: + panic("Tried to read write only register %d\n", idx); + break; + + default: + // invalid IPR + panic("Tried to read from invalid ipr %d\n", idx); + break; + } + + return retval; +} + +// Cause the simulator to break when changing to the following IPL +int break_ipl = -1; + +void +ISA::setIpr(int idx, uint64_t val, ThreadContext *tc) +{ + if (tc->misspeculating()) + return; + + switch (idx) { + case IPR_PALtemp0: + case IPR_PALtemp1: + case IPR_PALtemp2: + case IPR_PALtemp3: + case IPR_PALtemp4: + case IPR_PALtemp5: + case IPR_PALtemp6: + case IPR_PALtemp7: + case IPR_PALtemp8: + case IPR_PALtemp9: + case IPR_PALtemp10: + case IPR_PALtemp11: + case IPR_PALtemp12: + case IPR_PALtemp13: + case IPR_PALtemp14: + case IPR_PALtemp15: + case IPR_PALtemp16: + case IPR_PALtemp17: + case IPR_PALtemp18: + case IPR_PALtemp19: + case IPR_PALtemp20: + case IPR_PALtemp21: + case IPR_PALtemp22: + case IPR_PAL_BASE: + case IPR_IC_PERR_STAT: + case IPR_DC_PERR_STAT: + case IPR_PMCTR: + // write entire quad w/ no side-effect + ipr[idx] = val; + break; + + case IPR_CC_CTL: + // This IPR resets the cycle counter. We assume this only + // happens once... let's verify that. + assert(ipr[idx] == 0); + ipr[idx] = 1; + break; + + case IPR_CC: + // This IPR only writes the upper 64 bits. It's ok to write + // all 64 here since we mask out the lower 32 in rpcc (see + // isa_desc). + ipr[idx] = val; + break; + + case IPR_PALtemp23: + // write entire quad w/ no side-effect + if (tc->getKernelStats()) + tc->getKernelStats()->context(ipr[idx], val, tc); + ipr[idx] = val; + break; + + case IPR_DTB_PTE: + // write entire quad w/ no side-effect, tag is forthcoming + ipr[idx] = val; + break; + + case IPR_EXC_ADDR: + // second least significant bit in PC is always zero + ipr[idx] = val & ~2; + break; + + case IPR_ASTRR: + case IPR_ASTER: + // only write least significant four bits - privilege mask + ipr[idx] = val & 0xf; + break; + + case IPR_IPLR: +#ifdef DEBUG + if (break_ipl != -1 && break_ipl == (int)(val & 0x1f)) + Debug::breakpoint(); +#endif + + // only write least significant five bits - interrupt level + ipr[idx] = val & 0x1f; + if (tc->getKernelStats()) + tc->getKernelStats()->swpipl(ipr[idx]); + break; + + case IPR_DTB_CM: + if (val & 0x18) { + if (tc->getKernelStats()) + tc->getKernelStats()->mode(Kernel::user, tc); + } else { + if (tc->getKernelStats()) + tc->getKernelStats()->mode(Kernel::kernel, tc); + } + + case IPR_ICM: + // only write two mode bits - processor mode + ipr[idx] = val & 0x18; + break; + + case IPR_ALT_MODE: + // only write two mode bits - processor mode + ipr[idx] = val & 0x18; + break; + + case IPR_MCSR: + // more here after optimization... + ipr[idx] = val; + break; + + case IPR_SIRR: + // only write software interrupt mask + ipr[idx] = val & 0x7fff0; + break; + + case IPR_ICSR: + ipr[idx] = val & ULL(0xffffff0300); + break; + + case IPR_IVPTBR: + case IPR_MVPTBR: + ipr[idx] = val & ULL(0xffffffffc0000000); + break; + + case IPR_DC_TEST_CTL: + ipr[idx] = val & 0x1ffb; + break; + + case IPR_DC_MODE: + case IPR_MAF_MODE: + ipr[idx] = val & 0x3f; + break; + + case IPR_ITB_ASN: + ipr[idx] = val & 0x7f0; + break; + + case IPR_DTB_ASN: + ipr[idx] = val & ULL(0xfe00000000000000); + break; + + case IPR_EXC_SUM: + case IPR_EXC_MASK: + // any write to this register clears it + ipr[idx] = 0; + break; + + case IPR_INTID: + case IPR_SL_RCV: + case IPR_MM_STAT: + case IPR_ITB_PTE_TEMP: + case IPR_DTB_PTE_TEMP: + // read-only registers + panic("Tried to write read only ipr %d\n", idx); + + case IPR_HWINT_CLR: + case IPR_SL_XMIT: + case IPR_DC_FLUSH: + case IPR_IC_FLUSH: + // the following are write only + ipr[idx] = val; + break; + + case IPR_DTB_IA: + // really a control write + ipr[idx] = 0; + + tc->getDTBPtr()->flushAll(); + break; + + case IPR_DTB_IAP: + // really a control write + ipr[idx] = 0; + + tc->getDTBPtr()->flushProcesses(); + break; + + case IPR_DTB_IS: + // really a control write + ipr[idx] = val; + + tc->getDTBPtr()->flushAddr(val, DTB_ASN_ASN(ipr[IPR_DTB_ASN])); + break; + + case IPR_DTB_TAG: { + struct TlbEntry entry; + + // FIXME: granularity hints NYI... + if (DTB_PTE_GH(ipr[IPR_DTB_PTE]) != 0) + panic("PTE GH field != 0"); + + // write entire quad + ipr[idx] = val; + + // construct PTE for new entry + entry.ppn = DTB_PTE_PPN(ipr[IPR_DTB_PTE]); + entry.xre = DTB_PTE_XRE(ipr[IPR_DTB_PTE]); + entry.xwe = DTB_PTE_XWE(ipr[IPR_DTB_PTE]); + entry.fonr = DTB_PTE_FONR(ipr[IPR_DTB_PTE]); + entry.fonw = DTB_PTE_FONW(ipr[IPR_DTB_PTE]); + entry.asma = DTB_PTE_ASMA(ipr[IPR_DTB_PTE]); + entry.asn = DTB_ASN_ASN(ipr[IPR_DTB_ASN]); + + // insert new TAG/PTE value into data TLB + tc->getDTBPtr()->insert(val, entry); + } + break; + + case IPR_ITB_PTE: { + struct TlbEntry entry; + + // FIXME: granularity hints NYI... + if (ITB_PTE_GH(val) != 0) + panic("PTE GH field != 0"); + + // write entire quad + ipr[idx] = val; + + // construct PTE for new entry + entry.ppn = ITB_PTE_PPN(val); + entry.xre = ITB_PTE_XRE(val); + entry.xwe = 0; + entry.fonr = ITB_PTE_FONR(val); + entry.fonw = ITB_PTE_FONW(val); + entry.asma = ITB_PTE_ASMA(val); + entry.asn = ITB_ASN_ASN(ipr[IPR_ITB_ASN]); + + // insert new TAG/PTE value into data TLB + tc->getITBPtr()->insert(ipr[IPR_ITB_TAG], entry); + } + break; + + case IPR_ITB_IA: + // really a control write + ipr[idx] = 0; + + tc->getITBPtr()->flushAll(); + break; + + case IPR_ITB_IAP: + // really a control write + ipr[idx] = 0; + + tc->getITBPtr()->flushProcesses(); + break; + + case IPR_ITB_IS: + // really a control write + ipr[idx] = val; + + tc->getITBPtr()->flushAddr(val, ITB_ASN_ASN(ipr[IPR_ITB_ASN])); + break; + + default: + // invalid IPR + panic("Tried to write to invalid ipr %d\n", idx); + } + + // no error... +} + +void +copyIprs(ThreadContext *src, ThreadContext *dest) +{ + for (int i = 0; i < NumInternalProcRegs; ++i) + dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); +} + +} // namespace AlphaISA + +using namespace AlphaISA; + +Fault +SimpleThread::hwrei() +{ + PCState pc = pcState(); + if (!(pc.pc() & 0x3)) + return new UnimplementedOpcodeFault; + + pc.npc(readMiscRegNoEffect(IPR_EXC_ADDR)); + pcState(pc); + + CPA::cpa()->swAutoBegin(tc, pc.npc()); + + if (!misspeculating()) { + if (kernelStats) + kernelStats->hwrei(); + } + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + +/** + * Check for special simulator handling of specific PAL calls. + * If return value is false, actual PAL call will be suppressed. + */ +bool +SimpleThread::simPalCheck(int palFunc) +{ + if (kernelStats) + kernelStats->callpal(palFunc, tc); + + switch (palFunc) { + case PAL::halt: + halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (system->breakpoint()) + return false; + break; + } + + return true; +} diff --git a/simulators/gem5/src/arch/alpha/ev5.hh b/simulators/gem5/src/arch/alpha/ev5.hh new file mode 100644 index 00000000..5abc7e57 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/ev5.hh @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Nathan Binkert + * Ali Saidi + */ + +#ifndef __ARCH_ALPHA_EV5_HH__ +#define __ARCH_ALPHA_EV5_HH__ + +#include "arch/alpha/isa_traits.hh" + +class ThreadContext; + +namespace AlphaISA { + +const uint64_t AsnMask = ULL(0xff); +const int VAddrImplBits = 43; +const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1; +const Addr VAddrUnImplMask = ~VAddrImplMask; +inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; } +inline Addr VAddrVPN(Addr a) { return a >> PageShift; } +inline Addr VAddrOffset(Addr a) { return a & PageOffset; } +inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; } +inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; } + +inline bool PAddrIprSpace(Addr a) { return a >= ULL(0xFFFFFF00000); } +const int PAddrImplBits = 44; // for Tsunami +const Addr PAddrImplMask = (ULL(1) << PAddrImplBits) - 1; +const Addr PAddrUncachedBit39 = ULL(0x8000000000); +const Addr PAddrUncachedBit40 = ULL(0x10000000000); +const Addr PAddrUncachedBit43 = ULL(0x80000000000); +const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35> + +inline Addr +Phys2K0Seg(Addr addr) +{ + if (addr & PAddrUncachedBit43) { + addr &= PAddrUncachedMask; + addr |= PAddrUncachedBit40; + } + return addr | K0SegBase; +} + +inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; } +inline Addr DTB_PTE_PPN(uint64_t reg) +{ return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); } +inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } +inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; } +inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } +inline int DTB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } +inline int DTB_PTE_GH(uint64_t reg) { return reg >> 5 & 0x3; } +inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; } + +inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; } +inline Addr ITB_PTE_PPN(uint64_t reg) +{ return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); } +inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } +inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } +inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } +inline int ITB_PTE_GH(uint64_t reg) { return reg >> 5 & 0x3; } +inline bool ITB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; } + +inline uint64_t MCSR_SP(uint64_t reg) { return reg >> 1 & 0x3; } + +inline bool ICSR_SDE(uint64_t reg) { return reg >> 30 & 0x1; } +inline int ICSR_SPE(uint64_t reg) { return reg >> 28 & 0x3; } +inline bool ICSR_FPE(uint64_t reg) { return reg >> 26 & 0x1; } + +inline uint64_t ALT_MODE_AM(uint64_t reg) { return reg >> 3 & 0x3; } +inline uint64_t DTB_CM_CM(uint64_t reg) { return reg >> 3 & 0x3; } +inline uint64_t ICM_CM(uint64_t reg) { return reg >> 3 & 0x3; } + +const uint64_t MM_STAT_BAD_VA_MASK = ULL(0x0020); +const uint64_t MM_STAT_DTB_MISS_MASK = ULL(0x0010); +const uint64_t MM_STAT_FONW_MASK = ULL(0x0008); +const uint64_t MM_STAT_FONR_MASK = ULL(0x0004); +const uint64_t MM_STAT_ACV_MASK = ULL(0x0002); +const uint64_t MM_STAT_WR_MASK = ULL(0x0001); +inline int Opcode(MachInst inst) { return inst >> 26 & 0x3f; } +inline int Ra(MachInst inst) { return inst >> 21 & 0x1f; } + +const Addr PalBase = 0x4000; +const Addr PalMax = 0x10000; + +void copyIprs(ThreadContext *src, ThreadContext *dest); + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_EV5_HH__ diff --git a/simulators/gem5/src/arch/alpha/faults.cc b/simulators/gem5/src/arch/alpha/faults.cc new file mode 100644 index 00000000..e4a5c922 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/faults.cc @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Kevin Lim + */ + +#include "arch/alpha/ev5.hh" +#include "arch/alpha/faults.hh" +#include "arch/alpha/tlb.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "sim/process.hh" +#include "sim/full_system.hh" + +namespace AlphaISA { + +FaultName MachineCheckFault::_name = "mchk"; +FaultVect MachineCheckFault::_vect = 0x0401; +FaultStat MachineCheckFault::_count; + +FaultName AlignmentFault::_name = "unalign"; +FaultVect AlignmentFault::_vect = 0x0301; +FaultStat AlignmentFault::_count; + +FaultName ResetFault::_name = "reset"; +FaultVect ResetFault::_vect = 0x0001; +FaultStat ResetFault::_count; + +FaultName ArithmeticFault::_name = "arith"; +FaultVect ArithmeticFault::_vect = 0x0501; +FaultStat ArithmeticFault::_count; + +FaultName InterruptFault::_name = "interrupt"; +FaultVect InterruptFault::_vect = 0x0101; +FaultStat InterruptFault::_count; + +FaultName NDtbMissFault::_name = "dtb_miss_single"; +FaultVect NDtbMissFault::_vect = 0x0201; +FaultStat NDtbMissFault::_count; + +FaultName PDtbMissFault::_name = "dtb_miss_double"; +FaultVect PDtbMissFault::_vect = 0x0281; +FaultStat PDtbMissFault::_count; + +FaultName DtbPageFault::_name = "dtb_page_fault"; +FaultVect DtbPageFault::_vect = 0x0381; +FaultStat DtbPageFault::_count; + +FaultName DtbAcvFault::_name = "dtb_acv_fault"; +FaultVect DtbAcvFault::_vect = 0x0381; +FaultStat DtbAcvFault::_count; + +FaultName DtbAlignmentFault::_name = "unalign"; +FaultVect DtbAlignmentFault::_vect = 0x0301; +FaultStat DtbAlignmentFault::_count; + +FaultName ItbPageFault::_name = "itbmiss"; +FaultVect ItbPageFault::_vect = 0x0181; +FaultStat ItbPageFault::_count; + +FaultName ItbAcvFault::_name = "iaccvio"; +FaultVect ItbAcvFault::_vect = 0x0081; +FaultStat ItbAcvFault::_count; + +FaultName UnimplementedOpcodeFault::_name = "opdec"; +FaultVect UnimplementedOpcodeFault::_vect = 0x0481; +FaultStat UnimplementedOpcodeFault::_count; + +FaultName FloatEnableFault::_name = "fen"; +FaultVect FloatEnableFault::_vect = 0x0581; +FaultStat FloatEnableFault::_count; + +FaultName PalFault::_name = "pal"; +FaultVect PalFault::_vect = 0x2001; +FaultStat PalFault::_count; + +FaultName IntegerOverflowFault::_name = "intover"; +FaultVect IntegerOverflowFault::_vect = 0x0501; +FaultStat IntegerOverflowFault::_count; + +void +AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + FaultBase::invoke(tc); + if (!FullSystem) + return; + countStat()++; + + PCState pc = tc->pcState(); + + // exception restart address + if (setRestartAddress() || !(pc.pc() & 0x3)) + tc->setMiscRegNoEffect(IPR_EXC_ADDR, pc.pc()); + + if (skipFaultingInstruction()) { + // traps... skip faulting instruction. + tc->setMiscRegNoEffect(IPR_EXC_ADDR, + tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4); + } + + pc.set(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect()); + tc->pcState(pc); +} + +void +ArithmeticFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + FaultBase::invoke(tc); + if (!FullSystem) + return; + panic("Arithmetic traps are unimplemented!"); +} + +void +DtbFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + // Set fault address and flags. Even though we're modeling an + // EV5, we use the EV6 technique of not latching fault registers + // on VPTE loads (instead of locking the registers until IPR_VA is + // read, like the EV5). The EV6 approach is cleaner and seems to + // work with EV5 PAL code, but not the other way around. + if (!tc->misspeculating() && + reqFlags.noneSet(Request::VPTE | Request::PREFETCH)) { + // set VA register with faulting address + tc->setMiscRegNoEffect(IPR_VA, vaddr); + + // set MM_STAT register flags + MachInst machInst = inst->machInst; + tc->setMiscRegNoEffect(IPR_MM_STAT, + (((Opcode(machInst) & 0x3f) << 11) | + ((Ra(machInst) & 0x1f) << 6) | + (flags & 0x3f))); + + // set VA_FORM register with faulting formatted address + tc->setMiscRegNoEffect(IPR_VA_FORM, + tc->readMiscRegNoEffect(IPR_MVPTBR) | (vaddr.vpn() << 3)); + } + } + + AlphaFault::invoke(tc); +} + +void +ItbFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + if (!tc->misspeculating()) { + tc->setMiscRegNoEffect(IPR_ITB_TAG, pc); + tc->setMiscRegNoEffect(IPR_IFAULT_VA_FORM, + tc->readMiscRegNoEffect(IPR_IVPTBR) | (VAddr(pc).vpn() << 3)); + } + } + + AlphaFault::invoke(tc); +} + +void +ItbPageFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + ItbFault::invoke(tc); + return; + } + + Process *p = tc->getProcessPtr(); + TlbEntry entry; + bool success = p->pTable->lookup(pc, entry); + if (!success) { + panic("Tried to execute unmapped address %#x.\n", pc); + } else { + VAddr vaddr(pc); + tc->getITBPtr()->insert(vaddr.page(), entry); + } +} + +void +NDtbMissFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + DtbFault::invoke(tc, inst); + return; + } + + Process *p = tc->getProcessPtr(); + TlbEntry entry; + bool success = p->pTable->lookup(vaddr, entry); + if (!success) { + if (p->fixupStackFault(vaddr)) + success = p->pTable->lookup(vaddr, entry); + } + if (!success) { + panic("Tried to access unmapped address %#x.\n", (Addr)vaddr); + } else { + tc->getDTBPtr()->insert(vaddr.page(), entry); + } +} + +} // namespace AlphaISA + diff --git a/simulators/gem5/src/arch/alpha/faults.hh b/simulators/gem5/src/arch/alpha/faults.hh new file mode 100644 index 00000000..7eddd14e --- /dev/null +++ b/simulators/gem5/src/arch/alpha/faults.hh @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Kevin Lim + */ + +#ifndef __ARCH_ALPHA_FAULTS_HH__ +#define __ARCH_ALPHA_FAULTS_HH__ + +#include "arch/alpha/pagetable.hh" +#include "mem/request.hh" +#include "sim/faults.hh" + +// The design of the "name" and "vect" functions is in sim/faults.hh + +namespace AlphaISA { + +typedef const Addr FaultVect; + +class AlphaFault : public FaultBase +{ + protected: + virtual bool skipFaultingInstruction() {return false;} + virtual bool setRestartAddress() {return true;} + public: + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); + virtual FaultVect vect() = 0; + virtual FaultStat & countStat() = 0; +}; + +class MachineCheckFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class AlignmentFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + bool isAlignmentFault() const {return true;} +}; + +class ResetFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class ArithmeticFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + protected: + bool skipFaultingInstruction() {return true;} + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class InterruptFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + protected: + bool setRestartAddress() {return false;} + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbFault : public AlphaFault +{ + protected: + VAddr vaddr; + Request::Flags reqFlags; + uint64_t flags; + + public: + DtbFault(VAddr _vaddr, Request::Flags _reqFlags, uint64_t _flags) + : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) + { } + FaultName name() const = 0; + FaultVect vect() = 0; + FaultStat & countStat() = 0; + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class NDtbMissFault : public DtbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + NDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class PDtbMissFault : public DtbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + PDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbPageFault : public DtbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + DtbPageFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbAcvFault : public DtbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + DtbAcvFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbAlignmentFault : public DtbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + DtbAlignmentFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class ItbFault : public AlphaFault +{ + protected: + Addr pc; + + public: + ItbFault(Addr _pc) : pc(_pc) { } + FaultName name() const = 0; + FaultVect vect() = 0; + FaultStat & countStat() = 0; + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class ItbPageFault : public ItbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + ItbPageFault(Addr pc) : ItbFault(pc) { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class ItbAcvFault : public ItbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + ItbAcvFault(Addr pc) : ItbFault(pc) { } + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class UnimplementedOpcodeFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class FloatEnableFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class PalFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + protected: + bool skipFaultingInstruction() {return true;} + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class IntegerOverflowFault : public AlphaFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_FAULTS_HH__ diff --git a/simulators/gem5/src/arch/alpha/freebsd/system.cc b/simulators/gem5/src/arch/alpha/freebsd/system.cc new file mode 100644 index 00000000..303d5f76 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/freebsd/system.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ben Nash + */ + +/** + * @file + * Modifications for the FreeBSD kernel. + * Based on kern/linux/linux_system.cc. + * + */ + +#include "arch/alpha/freebsd/system.hh" +#include "arch/alpha/system.hh" +#include "arch/isa_traits.hh" +#include "arch/vtophys.hh" +#include "base/loader/symtab.hh" +#include "cpu/thread_context.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "sim/byteswap.hh" + +#define TIMER_FREQUENCY 1193180 + +using namespace std; +using namespace AlphaISA; + +FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p) + : AlphaSystem(p) +{ + /** + * Any time DELAY is called just skip the function. + * Shouldn't we actually emulate the delay? + */ + skipDelayEvent = addKernelFuncEvent("DELAY"); + skipCalibrateClocks = + addKernelFuncEvent("calibrate_clocks"); +} + +FreebsdAlphaSystem::~FreebsdAlphaSystem() +{ + delete skipDelayEvent; + delete skipCalibrateClocks; +} + +void +FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc) +{ + Addr ppc_vaddr = 0; + Addr timer_vaddr = 0; + + ppc_vaddr = (Addr)tc->readIntReg(17); + timer_vaddr = (Addr)tc->readIntReg(18); + + virtProxy.write(ppc_vaddr, (uint32_t)SimClock::Frequency); + virtProxy.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); +} + +void +FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ThreadContext *tc) +{ + SkipFuncEvent::process(tc); + ((FreebsdAlphaSystem *)tc->getSystemPtr())->doCalibrateClocks(tc); +} + +FreebsdAlphaSystem * +FreebsdAlphaSystemParams::create() +{ + return new FreebsdAlphaSystem(this); +} diff --git a/simulators/gem5/src/arch/alpha/freebsd/system.hh b/simulators/gem5/src/arch/alpha/freebsd/system.hh new file mode 100644 index 00000000..48f6238c --- /dev/null +++ b/simulators/gem5/src/arch/alpha/freebsd/system.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ben Nash + */ + +#ifndef __ARCH_ALPHA_FREEBSD_SYSTEM_HH__ +#define __ARCH_ALPHA_FREEBSD_SYSTEM_HH__ + +#include "arch/alpha/system.hh" +#include "kern/system_events.hh" +#include "params/FreebsdAlphaSystem.hh" +#include "sim/system.hh" + +class FreebsdAlphaSystem : public AlphaSystem +{ + private: + class SkipCalibrateClocksEvent : public SkipFuncEvent + { + public: + SkipCalibrateClocksEvent(PCEventQueue *q, const std::string &desc, + Addr addr) + : SkipFuncEvent(q, desc, addr) {} + virtual void process(ThreadContext *tc); + }; + + SkipFuncEvent *skipDelayEvent; + SkipCalibrateClocksEvent *skipCalibrateClocks; + + public: + typedef FreebsdAlphaSystemParams Params; + FreebsdAlphaSystem(Params *p); + ~FreebsdAlphaSystem(); + + void doCalibrateClocks(ThreadContext *tc); +}; + +#endif // __ARCH_ALPHA_FREEBSD_SYSTEM_HH__ diff --git a/simulators/gem5/src/arch/alpha/idle_event.cc b/simulators/gem5/src/arch/alpha/idle_event.cc new file mode 100644 index 00000000..bb68782e --- /dev/null +++ b/simulators/gem5/src/arch/alpha/idle_event.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Lisa Hsu + * Nathan Binkert + */ + +#include "arch/alpha/idle_event.hh" +#include "arch/alpha/kernel_stats.hh" +#include "cpu/thread_context.hh" + +using namespace AlphaISA; + +void +IdleStartEvent::process(ThreadContext *tc) +{ + if (tc->getKernelStats()) { + MiscReg val = tc->readMiscRegNoEffect(IPR_PALtemp23); + tc->getKernelStats()->setIdleProcess(val, tc); + } + remove(); +} diff --git a/simulators/gem5/src/arch/alpha/idle_event.hh b/simulators/gem5/src/arch/alpha/idle_event.hh new file mode 100644 index 00000000..97d5bdd6 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/idle_event.hh @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Lisa Hsu + * Ali Saidi + */ + +#ifndef __KERN_ALPHA_IDLE_EVENT_HH__ +#define __KERN_ALPHA_IDLE_EVENT_HH__ + +#include "cpu/pc_event.hh" + +class IdleStartEvent : public PCEvent +{ + public: + IdleStartEvent(PCEventQueue *q, const std::string &desc, Addr addr) + : PCEvent(q, desc, addr) + {} + virtual void process(ThreadContext *tc); +}; + +#endif // __KERN_ALPHA_IDLE_EVENT_HH__ diff --git a/simulators/gem5/src/arch/alpha/interrupts.cc b/simulators/gem5/src/arch/alpha/interrupts.cc new file mode 100644 index 00000000..4b5dc566 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/interrupts.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/alpha/interrupts.hh" + +AlphaISA::Interrupts * +AlphaInterruptsParams::create() +{ + return new AlphaISA::Interrupts(this); +} diff --git a/simulators/gem5/src/arch/alpha/interrupts.hh b/simulators/gem5/src/arch/alpha/interrupts.hh new file mode 100644 index 00000000..ce3108d7 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/interrupts.hh @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Kevin Lim + */ + +#ifndef __ARCH_ALPHA_INTERRUPT_HH__ +#define __ARCH_ALPHA_INTERRUPT_HH__ + +#include "arch/alpha/faults.hh" +#include "arch/alpha/isa_traits.hh" +#include "base/compiler.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/Flow.hh" +#include "debug/Interrupt.hh" +#include "params/AlphaInterrupts.hh" +#include "sim/sim_object.hh" + +namespace AlphaISA { + +class Interrupts : public SimObject +{ + private: + bool newInfoSet; + int newIpl; + int newSummary; + BaseCPU * cpu; + + protected: + uint64_t interrupts[NumInterruptLevels]; + uint64_t intstatus; + + public: + typedef AlphaInterruptsParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + Interrupts(Params * p) : SimObject(p), cpu(NULL) + { + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; + newInfoSet = false; + } + + void + setCPU(BaseCPU * _cpu) + { + cpu = _cpu; + } + + void + post(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + if (index < 0 || index >= (int)sizeof(uint64_t) * 8) + panic("int_num out of bounds\n"); + + interrupts[int_num] |= 1 << index; + intstatus |= (ULL(1) << int_num); + } + + void + clear(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + if (index < 0 || index >= (int)sizeof(uint64_t) * 8) + panic("int_num out of bounds\n"); + + interrupts[int_num] &= ~(1 << index); + if (interrupts[int_num] == 0) + intstatus &= ~(ULL(1) << int_num); + } + + void + clearAll() + { + DPRINTF(Interrupt, "Interrupts all cleared\n"); + + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; + } + + void + serialize(std::ostream &os) + { + SERIALIZE_ARRAY(interrupts, NumInterruptLevels); + SERIALIZE_SCALAR(intstatus); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); + UNSERIALIZE_SCALAR(intstatus); + } + + bool + checkInterrupts(ThreadContext *tc) const + { + return (intstatus != 0) && !(tc->pcState().pc() & 0x3); + } + + Fault + getInterrupt(ThreadContext *tc) + { + uint64_t ipl = 0; + uint64_t summary = 0; + + if (tc->readMiscRegNoEffect(IPR_ASTRR)) + panic("asynchronous traps not implemented\n"); + + if (tc->readMiscRegNoEffect(IPR_SIRR)) { + for (uint64_t i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; + summary |= (ULL(1) << i); + } + } + } + + uint64_t interrupts = intstatus; + if (interrupts) { + for (uint64_t i = INTLEVEL_EXTERNAL_MIN; + i < INTLEVEL_EXTERNAL_MAX; i++) { + if (interrupts & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = i; + summary |= (ULL(1) << i); + } + } + } + + if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) { + newIpl = ipl; + newSummary = summary; + newInfoSet = true; + DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", + tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary); + + return new InterruptFault; + } else { + return NoFault; + } + } + + void + updateIntrInfo(ThreadContext *tc) + { + assert(newInfoSet); + tc->setMiscRegNoEffect(IPR_ISR, newSummary); + tc->setMiscRegNoEffect(IPR_INTID, newIpl); + newInfoSet = false; + } +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_INTERRUPT_HH__ + diff --git a/simulators/gem5/src/arch/alpha/ipr.cc b/simulators/gem5/src/arch/alpha/ipr.cc new file mode 100644 index 00000000..502ada5e --- /dev/null +++ b/simulators/gem5/src/arch/alpha/ipr.cc @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include +#include + +#include "arch/alpha/ipr.hh" + +namespace AlphaISA { + +md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = { + + //Write only + RAW_IPR_HWINT_CLR, // H/W interrupt clear register + RAW_IPR_SL_XMIT, // serial line transmit register + RAW_IPR_DC_FLUSH, + RAW_IPR_IC_FLUSH, // instruction cache flush control + RAW_IPR_ALT_MODE, // alternate mode register + RAW_IPR_DTB_IA, // DTLB invalidate all register + RAW_IPR_DTB_IAP, // DTLB invalidate all process register + RAW_IPR_ITB_IA, // ITLB invalidate all register + RAW_IPR_ITB_IAP, // ITLB invalidate all process register + + //Read only + RAW_IPR_INTID, // interrupt ID register + RAW_IPR_SL_RCV, // serial line receive register + RAW_IPR_MM_STAT, // data MMU fault status register + RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register + RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register + + RAW_IPR_ISR, // interrupt summary register + RAW_IPR_ITB_TAG, // ITLB tag register + RAW_IPR_ITB_PTE, // ITLB page table entry register + RAW_IPR_ITB_ASN, // ITLB address space register + RAW_IPR_ITB_IS, // ITLB invalidate select register + RAW_IPR_SIRR, // software interrupt request register + RAW_IPR_ASTRR, // asynchronous system trap request register + RAW_IPR_ASTER, // asynchronous system trap enable register + RAW_IPR_EXC_ADDR, // exception address register + RAW_IPR_EXC_SUM, // exception summary register + RAW_IPR_EXC_MASK, // exception mask register + RAW_IPR_PAL_BASE, // PAL base address register + RAW_IPR_ICM, // instruction current mode + RAW_IPR_IPLR, // interrupt priority level register + RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register + RAW_IPR_IVPTBR, // virtual page table base register + RAW_IPR_ICSR, // instruction control and status register + RAW_IPR_IC_PERR_STAT, // inst cache parity error status register + RAW_IPR_PMCTR, // performance counter register + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + RAW_IPR_PALtemp0, // local scratch + RAW_IPR_PALtemp1, // local scratch + RAW_IPR_PALtemp2, // entUna + RAW_IPR_PALtemp3, // CPU specific impure area pointer + RAW_IPR_PALtemp4, // memory management temp + RAW_IPR_PALtemp5, // memory management temp + RAW_IPR_PALtemp6, // memory management temp + RAW_IPR_PALtemp7, // entIF + RAW_IPR_PALtemp8, // intmask + RAW_IPR_PALtemp9, // entSys + RAW_IPR_PALtemp10, // ?? + RAW_IPR_PALtemp11, // entInt + RAW_IPR_PALtemp12, // entArith + RAW_IPR_PALtemp13, // reserved for platform specific PAL + RAW_IPR_PALtemp14, // reserved for platform specific PAL + RAW_IPR_PALtemp15, // reserved for platform specific PAL + RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17, // sysval + RAW_IPR_PALtemp18, // usp + RAW_IPR_PALtemp19, // ksp + RAW_IPR_PALtemp20, // PTBR + RAW_IPR_PALtemp21, // entMM + RAW_IPR_PALtemp22, // kgp + RAW_IPR_PALtemp23, // PCBB + + RAW_IPR_DTB_ASN, // DTLB address space number register + RAW_IPR_DTB_CM, // DTLB current mode register + RAW_IPR_DTB_TAG, // DTLB tag register + RAW_IPR_DTB_PTE, // DTLB page table entry register + + RAW_IPR_VA, // fault virtual address register + RAW_IPR_VA_FORM, // formatted virtual address register + RAW_IPR_MVPTBR, // MTU virtual page table base register + RAW_IPR_DTB_IS, // DTLB invalidate single register + RAW_IPR_CC, // cycle counter register + RAW_IPR_CC_CTL, // cycle counter control register + RAW_IPR_MCSR, // MTU control register + + RAW_IPR_DC_PERR_STAT, // Dcache parity error status register + RAW_IPR_DC_TEST_CTL, // Dcache test tag control register + RAW_IPR_DC_TEST_TAG, // Dcache test tag register + RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register + RAW_IPR_DC_MODE, // Dcache mode register + RAW_IPR_MAF_MODE // miss address file mode register +}; + +int IprToMiscRegIndex[MaxInternalProcRegs]; + +void +initializeIprTable() +{ + static bool initialized = false; + if (initialized) + return; + + memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int)); + + for (int x = 0; x < NumInternalProcRegs; x++) + IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x; +} + +} // namespace AlphaISA + diff --git a/simulators/gem5/src/arch/alpha/ipr.hh b/simulators/gem5/src/arch/alpha/ipr.hh new file mode 100644 index 00000000..4e7bf1fa --- /dev/null +++ b/simulators/gem5/src/arch/alpha/ipr.hh @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_IPR_HH__ +#define __ARCH_ALPHA_IPR_HH__ + +namespace AlphaISA { + +//////////////////////////////////////////////////////////////////////// +// +// Internal Processor Reigsters +// +enum md_ipr_names { + RAW_IPR_ISR = 0x100, // interrupt summary + RAW_IPR_ITB_TAG = 0x101, // ITLB tag + RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry + RAW_IPR_ITB_ASN = 0x103, // ITLB address space + RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp + RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all + RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process + RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select + RAW_IPR_SIRR = 0x108, // software interrupt request + RAW_IPR_ASTRR = 0x109, // asynchronous system trap request + RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable + RAW_IPR_EXC_ADDR = 0x10b, // exception address + RAW_IPR_EXC_SUM = 0x10c, // exception summary + RAW_IPR_EXC_MASK = 0x10d, // exception mask + RAW_IPR_PAL_BASE = 0x10e, // PAL base address + RAW_IPR_ICM = 0x10f, // instruction current mode + RAW_IPR_IPLR = 0x110, // interrupt priority level + RAW_IPR_INTID = 0x111, // interrupt ID + RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr + RAW_IPR_IVPTBR = 0x113, // virtual page table base + RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear + RAW_IPR_SL_XMIT = 0x116, // serial line transmit + RAW_IPR_SL_RCV = 0x117, // serial line receive + RAW_IPR_ICSR = 0x118, // instruction control and status + RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control + RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status + RAW_IPR_PMCTR = 0x11c, // performance counter + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + RAW_IPR_PALtemp0 = 0x140, // local scratch + RAW_IPR_PALtemp1 = 0x141, // local scratch + RAW_IPR_PALtemp2 = 0x142, // entUna + RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer + RAW_IPR_PALtemp4 = 0x144, // memory management temp + RAW_IPR_PALtemp5 = 0x145, // memory management temp + RAW_IPR_PALtemp6 = 0x146, // memory management temp + RAW_IPR_PALtemp7 = 0x147, // entIF + RAW_IPR_PALtemp8 = 0x148, // intmask + RAW_IPR_PALtemp9 = 0x149, // entSys + RAW_IPR_PALtemp10 = 0x14a, // ?? + RAW_IPR_PALtemp11 = 0x14b, // entInt + RAW_IPR_PALtemp12 = 0x14c, // entArith + RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL + RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL + RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL + RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17 = 0x151, // sysval + RAW_IPR_PALtemp18 = 0x152, // usp + RAW_IPR_PALtemp19 = 0x153, // ksp + RAW_IPR_PALtemp20 = 0x154, // PTBR + RAW_IPR_PALtemp21 = 0x155, // entMM + RAW_IPR_PALtemp22 = 0x156, // kgp + RAW_IPR_PALtemp23 = 0x157, // PCBB + + RAW_IPR_DTB_ASN = 0x200, // DTLB address space number + RAW_IPR_DTB_CM = 0x201, // DTLB current mode + RAW_IPR_DTB_TAG = 0x202, // DTLB tag + RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry + RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary + + RAW_IPR_MM_STAT = 0x205, // data MMU fault status + RAW_IPR_VA = 0x206, // fault virtual address + RAW_IPR_VA_FORM = 0x207, // formatted virtual address + RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base + RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process + RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all + RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single + RAW_IPR_ALT_MODE = 0x20c, // alternate mode + RAW_IPR_CC = 0x20d, // cycle counter + RAW_IPR_CC_CTL = 0x20e, // cycle counter control + RAW_IPR_MCSR = 0x20f, // MTU control + + RAW_IPR_DC_FLUSH = 0x210, + RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status + RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control + RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag + RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary + RAW_IPR_DC_MODE = 0x216, // Dcache mode + RAW_IPR_MAF_MODE = 0x217, // miss address file mode + + MaxInternalProcRegs // number of IPRs +}; + +enum MiscRegIpr +{ + //Write only + MinWriteOnlyIpr, + IPR_HWINT_CLR = MinWriteOnlyIpr, + IPR_SL_XMIT, + IPR_DC_FLUSH, + IPR_IC_FLUSH, + IPR_ALT_MODE, + IPR_DTB_IA, + IPR_DTB_IAP, + IPR_ITB_IA, + MaxWriteOnlyIpr, + IPR_ITB_IAP = MaxWriteOnlyIpr, + + //Read only + MinReadOnlyIpr, + IPR_INTID = MinReadOnlyIpr, + IPR_SL_RCV, + IPR_MM_STAT, + IPR_ITB_PTE_TEMP, + MaxReadOnlyIpr, + IPR_DTB_PTE_TEMP = MaxReadOnlyIpr, + + IPR_ISR, + IPR_ITB_TAG, + IPR_ITB_PTE, + IPR_ITB_ASN, + IPR_ITB_IS, + IPR_SIRR, + IPR_ASTRR, + IPR_ASTER, + IPR_EXC_ADDR, + IPR_EXC_SUM, + IPR_EXC_MASK, + IPR_PAL_BASE, + IPR_ICM, + IPR_IPLR, + IPR_IFAULT_VA_FORM, + IPR_IVPTBR, + IPR_ICSR, + IPR_IC_PERR_STAT, + IPR_PMCTR, + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + IPR_PALtemp0, + IPR_PALtemp1, + IPR_PALtemp2, + IPR_PALtemp3, + IPR_PALtemp4, + IPR_PALtemp5, + IPR_PALtemp6, + IPR_PALtemp7, + IPR_PALtemp8, + IPR_PALtemp9, + IPR_PALtemp10, + IPR_PALtemp11, + IPR_PALtemp12, + IPR_PALtemp13, + IPR_PALtemp14, + IPR_PALtemp15, + IPR_PALtemp16, + IPR_PALtemp17, + IPR_PALtemp18, + IPR_PALtemp19, + IPR_PALtemp20, + IPR_PALtemp21, + IPR_PALtemp22, + IPR_PALtemp23, + + IPR_DTB_ASN, + IPR_DTB_CM, + IPR_DTB_TAG, + IPR_DTB_PTE, + + IPR_VA, + IPR_VA_FORM, + IPR_MVPTBR, + IPR_DTB_IS, + IPR_CC, + IPR_CC_CTL, + IPR_MCSR, + + IPR_DC_PERR_STAT, + IPR_DC_TEST_CTL, + IPR_DC_TEST_TAG, + IPR_DC_TEST_TAG_TEMP, + IPR_DC_MODE, + IPR_MAF_MODE, + + NumInternalProcRegs // number of IPR registers +}; + +inline bool +IprIsWritable(int index) +{ + return index < MinReadOnlyIpr || index > MaxReadOnlyIpr; +} + +inline bool +IprIsReadable(int index) +{ + return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr; +} + +extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs]; +extern int IprToMiscRegIndex[MaxInternalProcRegs]; + +void initializeIprTable(); + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_IPR_HH__ diff --git a/simulators/gem5/src/arch/alpha/isa.cc b/simulators/gem5/src/arch/alpha/isa.cc new file mode 100644 index 00000000..5fd34a49 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa.cc @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include + +#include "arch/alpha/isa.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "sim/serialize.hh" + +namespace AlphaISA +{ + +void +ISA::serialize(EventManager *em, std::ostream &os) +{ + SERIALIZE_SCALAR(fpcr); + SERIALIZE_SCALAR(uniq); + SERIALIZE_SCALAR(lock_flag); + SERIALIZE_SCALAR(lock_addr); + SERIALIZE_ARRAY(ipr, NumInternalProcRegs); +} + +void +ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(fpcr); + UNSERIALIZE_SCALAR(uniq); + UNSERIALIZE_SCALAR(lock_flag); + UNSERIALIZE_SCALAR(lock_addr); + UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); +} + + +MiscReg +ISA::readMiscRegNoEffect(int misc_reg, ThreadID tid) +{ + switch (misc_reg) { + case MISCREG_FPCR: + return fpcr; + case MISCREG_UNIQ: + return uniq; + case MISCREG_LOCKFLAG: + return lock_flag; + case MISCREG_LOCKADDR: + return lock_addr; + case MISCREG_INTR: + return intr_flag; + default: + assert(misc_reg < NumInternalProcRegs); + return ipr[misc_reg]; + } +} + +MiscReg +ISA::readMiscReg(int misc_reg, ThreadContext *tc, ThreadID tid) +{ + switch (misc_reg) { + case MISCREG_FPCR: + return fpcr; + case MISCREG_UNIQ: + return uniq; + case MISCREG_LOCKFLAG: + return lock_flag; + case MISCREG_LOCKADDR: + return lock_addr; + case MISCREG_INTR: + return intr_flag; + default: + return readIpr(misc_reg, tc); + } +} + +void +ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid) +{ + switch (misc_reg) { + case MISCREG_FPCR: + fpcr = val; + return; + case MISCREG_UNIQ: + uniq = val; + return; + case MISCREG_LOCKFLAG: + lock_flag = val; + return; + case MISCREG_LOCKADDR: + lock_addr = val; + return; + case MISCREG_INTR: + intr_flag = val; + return; + default: + assert(misc_reg < NumInternalProcRegs); + ipr[misc_reg] = val; + return; + } +} + +void +ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc, + ThreadID tid) +{ + switch (misc_reg) { + case MISCREG_FPCR: + fpcr = val; + return; + case MISCREG_UNIQ: + uniq = val; + return; + case MISCREG_LOCKFLAG: + lock_flag = val; + return; + case MISCREG_LOCKADDR: + lock_addr = val; + return; + case MISCREG_INTR: + intr_flag = val; + return; + default: + setIpr(misc_reg, val, tc); + return; + } +} + +} diff --git a/simulators/gem5/src/arch/alpha/isa.hh b/simulators/gem5/src/arch/alpha/isa.hh new file mode 100644 index 00000000..f1bfcebe --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa.hh @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ALPHA_ISA_HH__ +#define __ARCH_ALPHA_ISA_HH__ + +#include +#include +#include + +#include "arch/alpha/registers.hh" +#include "arch/alpha/types.hh" +#include "base/types.hh" + +class BaseCPU; +class Checkpoint; +class EventManager; +class ThreadContext; + +namespace AlphaISA +{ + class ISA + { + public: + typedef uint64_t InternalProcReg; + + protected: + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + int intr_flag; + + InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + + protected: + InternalProcReg readIpr(int idx, ThreadContext *tc); + void setIpr(int idx, InternalProcReg val, ThreadContext *tc); + + public: + + MiscReg readMiscRegNoEffect(int misc_reg, ThreadID tid = 0); + MiscReg readMiscReg(int misc_reg, ThreadContext *tc, ThreadID tid = 0); + + void setMiscRegNoEffect(int misc_reg, const MiscReg &val, + ThreadID tid = 0); + void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc, + ThreadID tid = 0); + + void + clear() + { + fpcr = 0; + uniq = 0; + lock_flag = 0; + lock_addr = 0; + intr_flag = 0; + memset(ipr, 0, sizeof(ipr)); + } + + void serialize(EventManager *em, std::ostream &os); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion); + + int + flattenIntIndex(int reg) + { + return reg; + } + + int + flattenFloatIndex(int reg) + { + return reg; + } + + ISA() + { + clear(); + initializeIprTable(); + } + }; +} + +#endif diff --git a/simulators/gem5/src/arch/alpha/isa/branch.isa b/simulators/gem5/src/arch/alpha/isa/branch.isa new file mode 100644 index 00000000..def6f3c1 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/branch.isa @@ -0,0 +1,274 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Control transfer instructions +// + +output header {{ + + /** + * Base class for instructions whose disassembly is not purely a + * function of the machine instruction (i.e., it depends on the + * PC). This class overrides the disassemble() method to check + * the PC and symbol table values before re-using a cached + * disassembly string. This is necessary for branches and jumps, + * where the disassembly string includes the target address (which + * may depend on the PC and/or symbol table). + */ + class PCDependentDisassembly : public AlphaStaticInst + { + protected: + /// Cached program counter from last disassembly + mutable Addr cachedPC; + /// Cached symbol table pointer from last disassembly + mutable const SymbolTable *cachedSymtab; + + /// Constructor + PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) + { + } + + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branches (PC-relative control transfers), + * conditional or unconditional. + */ + class Branch : public PCDependentDisassembly + { + protected: + /// Displacement to target address (signed). + int32_t disp; + + /// Constructor. + Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(BRDISP << 2) + { + } + + AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for jumps (register-indirect control transfers). In + * the Alpha ISA, these are always unconditional. + */ + class Jump : public PCDependentDisassembly + { + protected: + + /// Displacement to target address (signed). + int32_t disp; + + public: + /// Constructor + Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(BRDISP) + { + } + + AlphaISA::PCState branchTarget(ThreadContext *tc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + AlphaISA::PCState + Branch::branchTarget(const AlphaISA::PCState &branchPC) const + { + return branchPC.pc() + 4 + disp; + } + + AlphaISA::PCState + Jump::branchTarget(ThreadContext *tc) const + { + PCState pc = tc->pcState(); + uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); + pc.set((Rb & ~3) | (pc.pc() & 1)); + return pc; + } + + const std::string & + PCDependentDisassembly::disassemble(Addr pc, + const SymbolTable *symtab) const + { + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) + { + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; + } + + std::string + Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + else if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numSrcRegs == 0 && _numDestRegs == 0) { + printReg(ss, 31); + ss << ","; + } +#endif + + Addr target = pc + 4 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numDestRegs == 0) { + printReg(ss, 31); + ss << ","; + } +#endif + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + + ccprintf(ss, "(r%d)", RB); + + return ss.str(); + } +}}; + +def template JumpOrBranchDecode {{ + return (RA == 31) + ? (StaticInst *)new %(class_name)s(machInst) + : (StaticInst *)new %(class_name)sAndLink(machInst); +}}; + +def format CondBranch(code) {{ + code = ''' + bool cond; + %(code)s; + if (cond) + NPC = NPC + disp; + else + NPC = NPC; + ''' % { "code" : code } + iop = InstObjParams(name, Name, 'Branch', code, + ('IsDirectControl', 'IsCondControl')) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +let {{ +def UncondCtrlBase(name, Name, base_class, npc_expr, flags): + # Declare basic control transfer w/o link (i.e. link reg is R31) + nolink_code = 'NPC = %s;\n' % npc_expr + nolink_iop = InstObjParams(name, Name, base_class, + nolink_code, flags) + header_output = BasicDeclare.subst(nolink_iop) + decoder_output = BasicConstructor.subst(nolink_iop) + exec_output = BasicExecute.subst(nolink_iop) + + # Generate declaration of '*AndLink' version, append to decls + link_code = 'Ra = NPC & ~3;\n' + nolink_code + link_iop = InstObjParams(name, Name + 'AndLink', base_class, + link_code, flags) + header_output += BasicDeclare.subst(link_iop) + decoder_output += BasicConstructor.subst(link_iop) + exec_output += BasicExecute.subst(link_iop) + + # need to use link_iop for the decode template since it is expecting + # the shorter version of class_name (w/o "AndLink") + + return (header_output, decoder_output, + JumpOrBranchDecode.subst(nolink_iop), exec_output) +}}; + +def format UncondBranch(*flags) {{ + flags += ('IsUncondControl', 'IsDirectControl') + (header_output, decoder_output, decode_block, exec_output) = \ + UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) +}}; + +def format Jump(*flags) {{ + flags += ('IsUncondControl', 'IsIndirectControl') + (header_output, decoder_output, decode_block, exec_output) = \ + UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) +}}; + + diff --git a/simulators/gem5/src/arch/alpha/isa/decoder.isa b/simulators/gem5/src/arch/alpha/isa/decoder.isa new file mode 100644 index 00000000..9785e217 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/decoder.isa @@ -0,0 +1,1065 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2006 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// The actual decoder specification +// + +decode OPCODE default Unknown::unknown() { + + format LoadAddress { + 0x08: lda({{ Ra = Rb + disp; }}); + 0x09: ldah({{ Ra = Rb + (disp << 16); }}); + } + + format LoadOrNop { + 0x0a: ldbu({{ Ra_uq = Mem_ub; }}); + 0x0c: ldwu({{ Ra_uq = Mem_uw; }}); + 0x0b: ldq_u({{ Ra = Mem_uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }}); + 0x23: ldt({{ Fa = Mem_df; }}); + 0x2a: ldl_l({{ Ra_sl = Mem_sl; }}, mem_flags = LLSC); + 0x2b: ldq_l({{ Ra_uq = Mem_uq; }}, mem_flags = LLSC); + } + + format LoadOrPrefetch { + 0x28: ldl({{ Ra_sl = Mem_sl; }}); + 0x29: ldq({{ Ra_uq = Mem_uq; }}, pf_flags = EVICT_NEXT); + // IsFloating flag on lds gets the prefetch to disassemble + // using f31 instead of r31... funcitonally it's unnecessary + 0x22: lds({{ Fa_uq = s_to_t(Mem_ul); }}, + pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating); + } + + format Store { + 0x0e: stb({{ Mem_ub = Ra<7:0>; }}); + 0x0d: stw({{ Mem_uw = Ra<15:0>; }}); + 0x2c: stl({{ Mem_ul = Ra<31:0>; }}); + 0x2d: stq({{ Mem_uq = Ra_uq; }}); + 0x0f: stq_u({{ Mem_uq = Ra_uq; }}, {{ EA = (Rb + disp) & ~7; }}); + 0x26: sts({{ Mem_ul = t_to_s(Fa_uq); }}); + 0x27: stt({{ Mem_df = Fa; }}); + } + + format StoreCond { + 0x2e: stl_c({{ Mem_ul = Ra<31:0>; }}, + {{ + uint64_t tmp = write_result; + // see stq_c + Ra = (tmp == 0 || tmp == 1) ? tmp : Ra; + if (tmp == 1) { + xc->setStCondFailures(0); + } + }}, mem_flags = LLSC, inst_flags = IsStoreConditional); + 0x2f: stq_c({{ Mem_uq = Ra; }}, + {{ + uint64_t tmp = write_result; + // If the write operation returns 0 or 1, then + // this was a conventional store conditional, + // and the value indicates the success/failure + // of the operation. If another value is + // returned, then this was a Turbolaser + // mailbox access, and we don't update the + // result register at all. + Ra = (tmp == 0 || tmp == 1) ? tmp : Ra; + if (tmp == 1) { + // clear failure counter... this is + // non-architectural and for debugging + // only. + xc->setStCondFailures(0); + } + }}, mem_flags = LLSC, inst_flags = IsStoreConditional); + } + + format IntegerOperate { + + 0x10: decode INTFUNC { // integer arithmetic operations + + 0x00: addl({{ Rc_sl = Ra_sl + Rb_or_imm_sl; }}); + 0x40: addlv({{ + int32_t tmp = Ra_sl + Rb_or_imm_sl; + // signed overflow occurs when operands have same sign + // and sign of result does not match. + if (Ra_sl<31:> == Rb_or_imm_sl<31:> && tmp<31:> != Ra_sl<31:>) + fault = new IntegerOverflowFault; + Rc_sl = tmp; + }}); + 0x02: s4addl({{ Rc_sl = (Ra_sl << 2) + Rb_or_imm_sl; }}); + 0x12: s8addl({{ Rc_sl = (Ra_sl << 3) + Rb_or_imm_sl; }}); + + 0x20: addq({{ Rc = Ra + Rb_or_imm; }}); + 0x60: addqv({{ + uint64_t tmp = Ra + Rb_or_imm; + // signed overflow occurs when operands have same sign + // and sign of result does not match. + if (Ra<63:> == Rb_or_imm<63:> && tmp<63:> != Ra<63:>) + fault = new IntegerOverflowFault; + Rc = tmp; + }}); + 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }}); + 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }}); + + 0x09: subl({{ Rc_sl = Ra_sl - Rb_or_imm_sl; }}); + 0x49: sublv({{ + int32_t tmp = Ra_sl - Rb_or_imm_sl; + // signed overflow detection is same as for add, + // except we need to look at the *complemented* + // sign bit of the subtrahend (Rb), i.e., if the initial + // signs are the *same* then no overflow can occur + if (Ra_sl<31:> != Rb_or_imm_sl<31:> && tmp<31:> != Ra_sl<31:>) + fault = new IntegerOverflowFault; + Rc_sl = tmp; + }}); + 0x0b: s4subl({{ Rc_sl = (Ra_sl << 2) - Rb_or_imm_sl; }}); + 0x1b: s8subl({{ Rc_sl = (Ra_sl << 3) - Rb_or_imm_sl; }}); + + 0x29: subq({{ Rc = Ra - Rb_or_imm; }}); + 0x69: subqv({{ + uint64_t tmp = Ra - Rb_or_imm; + // signed overflow detection is same as for add, + // except we need to look at the *complemented* + // sign bit of the subtrahend (Rb), i.e., if the initial + // signs are the *same* then no overflow can occur + if (Ra<63:> != Rb_or_imm<63:> && tmp<63:> != Ra<63:>) + fault = new IntegerOverflowFault; + Rc = tmp; + }}); + 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }}); + 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }}); + + 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }}); + 0x6d: cmple({{ Rc = (Ra_sq <= Rb_or_imm_sq); }}); + 0x4d: cmplt({{ Rc = (Ra_sq < Rb_or_imm_sq); }}); + 0x3d: cmpule({{ Rc = (Ra_uq <= Rb_or_imm_uq); }}); + 0x1d: cmpult({{ Rc = (Ra_uq < Rb_or_imm_uq); }}); + + 0x0f: cmpbge({{ + int hi = 7; + int lo = 0; + uint64_t tmp = 0; + for (int i = 0; i < 8; ++i) { + tmp |= (Ra_uq >= Rb_or_imm_uq) << i; + hi += 8; + lo += 8; + } + Rc = tmp; + }}); + } + + 0x11: decode INTFUNC { // integer logical operations + + 0x00: and({{ Rc = Ra & Rb_or_imm; }}); + 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }}); + 0x20: bis({{ Rc = Ra | Rb_or_imm; }}); + 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }}); + 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }}); + 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }}); + + // conditional moves + 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }}); + 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }}); + 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }}); + 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }}); + 0x44: cmovlt({{ Rc = (Ra_sq < 0) ? Rb_or_imm : Rc; }}); + 0x46: cmovge({{ Rc = (Ra_sq >= 0) ? Rb_or_imm : Rc; }}); + 0x64: cmovle({{ Rc = (Ra_sq <= 0) ? Rb_or_imm : Rc; }}); + 0x66: cmovgt({{ Rc = (Ra_sq > 0) ? Rb_or_imm : Rc; }}); + + // For AMASK, RA must be R31. + 0x61: decode RA { + 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }}); + } + + // For IMPLVER, RA must be R31 and the B operand + // must be the immediate value 1. + 0x6c: decode RA { + 31: decode IMM { + 1: decode INTIMM { + // return EV5 for FullSystem and EV6 otherwise + 1: implver({{ Rc = FullSystem ? 1 : 2 }}); + } + } + } + + // The mysterious 11.25... + 0x25: WarnUnimpl::eleven25(); + } + + 0x12: decode INTFUNC { + 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }}); + 0x34: srl({{ Rc = Ra_uq >> Rb_or_imm<5:0>; }}); + 0x3c: sra({{ Rc = Ra_sq >> Rb_or_imm<5:0>; }}); + + 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }}); + 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }}); + 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }}); + 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }}); + + 0x52: mskwh({{ + int bv = Rb_or_imm<2:0>; + Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra; + }}); + 0x62: msklh({{ + int bv = Rb_or_imm<2:0>; + Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra; + }}); + 0x72: mskqh({{ + int bv = Rb_or_imm<2:0>; + Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra; + }}); + + 0x06: extbl({{ Rc = (Ra_uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }}); + 0x16: extwl({{ Rc = (Ra_uq >> (Rb_or_imm<2:0> * 8))<15:0>; }}); + 0x26: extll({{ Rc = (Ra_uq >> (Rb_or_imm<2:0> * 8))<31:0>; }}); + 0x36: extql({{ Rc = (Ra_uq >> (Rb_or_imm<2:0> * 8)); }}); + + 0x5a: extwh({{ + Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }}); + 0x6a: extlh({{ + Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }}); + 0x7a: extqh({{ + Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }}); + + 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }}); + 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }}); + 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }}); + 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }}); + + 0x57: inswh({{ + int bv = Rb_or_imm<2:0>; + Rc = bv ? (Ra_uq<15:0> >> (64 - 8 * bv)) : 0; + }}); + 0x67: inslh({{ + int bv = Rb_or_imm<2:0>; + Rc = bv ? (Ra_uq<31:0> >> (64 - 8 * bv)) : 0; + }}); + 0x77: insqh({{ + int bv = Rb_or_imm<2:0>; + Rc = bv ? (Ra_uq >> (64 - 8 * bv)) : 0; + }}); + + 0x30: zap({{ + uint64_t zapmask = 0; + for (int i = 0; i < 8; ++i) { + if (Rb_or_imm) + zapmask |= (mask(8) << (i * 8)); + } + Rc = Ra & ~zapmask; + }}); + 0x31: zapnot({{ + uint64_t zapmask = 0; + for (int i = 0; i < 8; ++i) { + if (!Rb_or_imm) + zapmask |= (mask(8) << (i * 8)); + } + Rc = Ra & ~zapmask; + }}); + } + + 0x13: decode INTFUNC { // integer multiplies + 0x00: mull({{ Rc_sl = Ra_sl * Rb_or_imm_sl; }}, IntMultOp); + 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp); + 0x30: umulh({{ + uint64_t hi, lo; + mul128(Ra, Rb_or_imm, hi, lo); + Rc = hi; + }}, IntMultOp); + 0x40: mullv({{ + // 32-bit multiply with trap on overflow + int64_t Rax = Ra_sl; // sign extended version of Ra_sl + int64_t Rbx = Rb_or_imm_sl; + int64_t tmp = Rax * Rbx; + // To avoid overflow, all the upper 32 bits must match + // the sign bit of the lower 32. We code this as + // checking the upper 33 bits for all 0s or all 1s. + uint64_t sign_bits = tmp<63:31>; + if (sign_bits != 0 && sign_bits != mask(33)) + fault = new IntegerOverflowFault; + Rc_sl = tmp<31:0>; + }}, IntMultOp); + 0x60: mulqv({{ + // 64-bit multiply with trap on overflow + uint64_t hi, lo; + mul128(Ra, Rb_or_imm, hi, lo); + // all the upper 64 bits must match the sign bit of + // the lower 64 + if (!((hi == 0 && lo<63:> == 0) || + (hi == mask(64) && lo<63:> == 1))) + fault = new IntegerOverflowFault; + Rc = lo; + }}, IntMultOp); + } + + 0x1c: decode INTFUNC { + 0x00: decode RA { 31: sextb({{ Rc_sb = Rb_or_imm< 7:0>; }}); } + 0x01: decode RA { 31: sextw({{ Rc_sw = Rb_or_imm<15:0>; }}); } + + 0x30: ctpop({{ + uint64_t count = 0; + for (int i = 0; Rb<63:i>; ++i) { + if (Rb == 0x1) + ++count; + } + Rc = count; + }}, IntAluOp); + + 0x31: perr({{ + uint64_t temp = 0; + int hi = 7; + int lo = 0; + for (int i = 0; i < 8; ++i) { + uint8_t ra_ub = Ra_uq; + uint8_t rb_ub = Rb_uq; + temp += (ra_ub >= rb_ub) ? + (ra_ub - rb_ub) : (rb_ub - ra_ub); + hi += 8; + lo += 8; + } + Rc = temp; + }}); + + 0x32: ctlz({{ + uint64_t count = 0; + uint64_t temp = Rb; + if (temp<63:32>) temp >>= 32; else count += 32; + if (temp<31:16>) temp >>= 16; else count += 16; + if (temp<15:8>) temp >>= 8; else count += 8; + if (temp<7:4>) temp >>= 4; else count += 4; + if (temp<3:2>) temp >>= 2; else count += 2; + if (temp<1:1>) temp >>= 1; else count += 1; + if ((temp<0:0>) != 0x1) count += 1; + Rc = count; + }}, IntAluOp); + + 0x33: cttz({{ + uint64_t count = 0; + uint64_t temp = Rb; + if (!(temp<31:0>)) { temp >>= 32; count += 32; } + if (!(temp<15:0>)) { temp >>= 16; count += 16; } + if (!(temp<7:0>)) { temp >>= 8; count += 8; } + if (!(temp<3:0>)) { temp >>= 4; count += 4; } + if (!(temp<1:0>)) { temp >>= 2; count += 2; } + if (!(temp<0:0> & ULL(0x1))) { + temp >>= 1; count += 1; + } + if (!(temp<0:0> & ULL(0x1))) count += 1; + Rc = count; + }}, IntAluOp); + + + 0x34: unpkbw({{ + Rc = (Rb_uq<7:0> + | (Rb_uq<15:8> << 16) + | (Rb_uq<23:16> << 32) + | (Rb_uq<31:24> << 48)); + }}, IntAluOp); + + 0x35: unpkbl({{ + Rc = (Rb_uq<7:0> | (Rb_uq<15:8> << 32)); + }}, IntAluOp); + + 0x36: pkwb({{ + Rc = (Rb_uq<7:0> + | (Rb_uq<23:16> << 8) + | (Rb_uq<39:32> << 16) + | (Rb_uq<55:48> << 24)); + }}, IntAluOp); + + 0x37: pklb({{ + Rc = (Rb_uq<7:0> | (Rb_uq<39:32> << 8)); + }}, IntAluOp); + + 0x38: minsb8({{ + uint64_t temp = 0; + int hi = 63; + int lo = 56; + for (int i = 7; i >= 0; --i) { + int8_t ra_sb = Ra_uq; + int8_t rb_sb = Rb_uq; + temp = ((temp << 8) + | ((ra_sb < rb_sb) ? Ra_uq + : Rb_uq)); + hi -= 8; + lo -= 8; + } + Rc = temp; + }}); + + 0x39: minsw4({{ + uint64_t temp = 0; + int hi = 63; + int lo = 48; + for (int i = 3; i >= 0; --i) { + int16_t ra_sw = Ra_uq; + int16_t rb_sw = Rb_uq; + temp = ((temp << 16) + | ((ra_sw < rb_sw) ? Ra_uq + : Rb_uq)); + hi -= 16; + lo -= 16; + } + Rc = temp; + }}); + + 0x3a: minub8({{ + uint64_t temp = 0; + int hi = 63; + int lo = 56; + for (int i = 7; i >= 0; --i) { + uint8_t ra_ub = Ra_uq; + uint8_t rb_ub = Rb_uq; + temp = ((temp << 8) + | ((ra_ub < rb_ub) ? Ra_uq + : Rb_uq)); + hi -= 8; + lo -= 8; + } + Rc = temp; + }}); + + 0x3b: minuw4({{ + uint64_t temp = 0; + int hi = 63; + int lo = 48; + for (int i = 3; i >= 0; --i) { + uint16_t ra_sw = Ra_uq; + uint16_t rb_sw = Rb_uq; + temp = ((temp << 16) + | ((ra_sw < rb_sw) ? Ra_uq + : Rb_uq)); + hi -= 16; + lo -= 16; + } + Rc = temp; + }}); + + 0x3c: maxub8({{ + uint64_t temp = 0; + int hi = 63; + int lo = 56; + for (int i = 7; i >= 0; --i) { + uint8_t ra_ub = Ra_uq; + uint8_t rb_ub = Rb_uq; + temp = ((temp << 8) + | ((ra_ub > rb_ub) ? Ra_uq + : Rb_uq)); + hi -= 8; + lo -= 8; + } + Rc = temp; + }}); + + 0x3d: maxuw4({{ + uint64_t temp = 0; + int hi = 63; + int lo = 48; + for (int i = 3; i >= 0; --i) { + uint16_t ra_uw = Ra_uq; + uint16_t rb_uw = Rb_uq; + temp = ((temp << 16) + | ((ra_uw > rb_uw) ? Ra_uq + : Rb_uq)); + hi -= 16; + lo -= 16; + } + Rc = temp; + }}); + + 0x3e: maxsb8({{ + uint64_t temp = 0; + int hi = 63; + int lo = 56; + for (int i = 7; i >= 0; --i) { + int8_t ra_sb = Ra_uq; + int8_t rb_sb = Rb_uq; + temp = ((temp << 8) + | ((ra_sb > rb_sb) ? Ra_uq + : Rb_uq)); + hi -= 8; + lo -= 8; + } + Rc = temp; + }}); + + 0x3f: maxsw4({{ + uint64_t temp = 0; + int hi = 63; + int lo = 48; + for (int i = 3; i >= 0; --i) { + int16_t ra_sw = Ra_uq; + int16_t rb_sw = Rb_uq; + temp = ((temp << 16) + | ((ra_sw > rb_sw) ? Ra_uq + : Rb_uq)); + hi -= 16; + lo -= 16; + } + Rc = temp; + }}); + + format BasicOperateWithNopCheck { + 0x70: decode RB { + 31: ftoit({{ Rc = Fa_uq; }}, FloatCvtOp); + } + 0x78: decode RB { + 31: ftois({{ Rc_sl = t_to_s(Fa_uq); }}, + FloatCvtOp); + } + } + } + } + + // Conditional branches. + format CondBranch { + 0x39: beq({{ cond = (Ra == 0); }}); + 0x3d: bne({{ cond = (Ra != 0); }}); + 0x3e: bge({{ cond = (Ra_sq >= 0); }}); + 0x3f: bgt({{ cond = (Ra_sq > 0); }}); + 0x3b: ble({{ cond = (Ra_sq <= 0); }}); + 0x3a: blt({{ cond = (Ra_sq < 0); }}); + 0x38: blbc({{ cond = ((Ra & 1) == 0); }}); + 0x3c: blbs({{ cond = ((Ra & 1) == 1); }}); + + 0x31: fbeq({{ cond = (Fa == 0); }}); + 0x35: fbne({{ cond = (Fa != 0); }}); + 0x36: fbge({{ cond = (Fa >= 0); }}); + 0x37: fbgt({{ cond = (Fa > 0); }}); + 0x33: fble({{ cond = (Fa <= 0); }}); + 0x32: fblt({{ cond = (Fa < 0); }}); + } + + // unconditional branches + format UncondBranch { + 0x30: br(); + 0x34: bsr(IsCall); + } + + // indirect branches + 0x1a: decode JMPFUNC { + format Jump { + 0: jmp(); + 1: jsr(IsCall); + 2: ret(IsReturn); + 3: jsr_coroutine(IsCall, IsReturn); + } + } + + // Square root and integer-to-FP moves + 0x14: decode FP_SHORTFUNC { + // Integer to FP register moves must have RB == 31 + 0x4: decode RB { + 31: decode FP_FULLFUNC { + format BasicOperateWithNopCheck { + 0x004: itofs({{ Fc_uq = s_to_t(Ra_ul); }}, FloatCvtOp); + 0x024: itoft({{ Fc_uq = Ra_uq; }}, FloatCvtOp); + 0x014: FailUnimpl::itoff(); // VAX-format conversion + } + } + } + + // Square root instructions must have FA == 31 + 0xb: decode FA { + 31: decode FP_TYPEFUNC { + format FloatingPointOperate { +#if SS_COMPATIBLE_FP + 0x0b: sqrts({{ + if (Fb < 0.0) + fault = new ArithmeticFault; + Fc = sqrt(Fb); + }}, FloatSqrtOp); +#else + 0x0b: sqrts({{ + if (Fb_sf < 0.0) + fault = new ArithmeticFault; + Fc_sf = sqrt(Fb_sf); + }}, FloatSqrtOp); +#endif + 0x2b: sqrtt({{ + if (Fb < 0.0) + fault = new ArithmeticFault; + Fc = sqrt(Fb); + }}, FloatSqrtOp); + } + } + } + + // VAX-format sqrtf and sqrtg are not implemented + 0xa: FailUnimpl::sqrtfg(); + } + + // IEEE floating point + 0x16: decode FP_SHORTFUNC_TOP2 { + // The top two bits of the short function code break this + // space into four groups: binary ops, compares, reserved, and + // conversions. See Table 4-12 of AHB. There are different + // special cases in these different groups, so we decode on + // these top two bits first just to select a decode strategy. + // Most of these instructions may have various trapping and + // rounding mode flags set; these are decoded in the + // FloatingPointDecode template used by the + // FloatingPointOperate format. + + // add/sub/mul/div: just decode on the short function code + // and source type. All valid trapping and rounding modes apply. + 0: decode FP_TRAPMODE { + // check for valid trapping modes here + 0,1,5,7: decode FP_TYPEFUNC { + format FloatingPointOperate { +#if SS_COMPATIBLE_FP + 0x00: adds({{ Fc = Fa + Fb; }}); + 0x01: subs({{ Fc = Fa - Fb; }}); + 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp); + 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp); +#else + 0x00: adds({{ Fc_sf = Fa_sf + Fb_sf; }}); + 0x01: subs({{ Fc_sf = Fa_sf - Fb_sf; }}); + 0x02: muls({{ Fc_sf = Fa_sf * Fb_sf; }}, FloatMultOp); + 0x03: divs({{ Fc_sf = Fa_sf / Fb_sf; }}, FloatDivOp); +#endif + + 0x20: addt({{ Fc = Fa + Fb; }}); + 0x21: subt({{ Fc = Fa - Fb; }}); + 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp); + 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp); + } + } + } + + // Floating-point compare instructions must have the default + // rounding mode, and may use the default trapping mode or + // /SU. Both trapping modes are treated the same by M5; the + // only difference on the real hardware (as far a I can tell) + // is that without /SU you'd get an imprecise trap if you + // tried to compare a NaN with something else (instead of an + // "unordered" result). + 1: decode FP_FULLFUNC { + format BasicOperateWithNopCheck { + 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }}, + FloatCmpOp); + 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }}, + FloatCmpOp); + 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }}, + FloatCmpOp); + 0x0a4, 0x5a4: cmptun({{ // unordered + Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0; + }}, FloatCmpOp); + } + } + + // The FP-to-integer and integer-to-FP conversion insts + // require that FA be 31. + 3: decode FA { + 31: decode FP_TYPEFUNC { + format FloatingPointOperate { + 0x2f: decode FP_ROUNDMODE { + format FPFixedRounding { + // "chopped" i.e. round toward zero + 0: cvttq({{ Fc_sq = (int64_t)trunc(Fb); }}, + Chopped); + // round to minus infinity + 1: cvttq({{ Fc_sq = (int64_t)floor(Fb); }}, + MinusInfinity); + } + default: cvttq({{ Fc_sq = (int64_t)nearbyint(Fb); }}); + } + + // The cvtts opcode is overloaded to be cvtst if the trap + // mode is 2 or 6 (which are not valid otherwise) + 0x2c: decode FP_FULLFUNC { + format BasicOperateWithNopCheck { + // trap on denorm version "cvtst/s" is + // simulated same as cvtst + 0x2ac, 0x6ac: cvtst({{ Fc = Fb_sf; }}); + } + default: cvtts({{ Fc_sf = Fb; }}); + } + + // The trapping mode for integer-to-FP conversions + // must be /SUI or nothing; /U and /SU are not + // allowed. The full set of rounding modes are + // supported though. + 0x3c: decode FP_TRAPMODE { + 0,7: cvtqs({{ Fc_sf = Fb_sq; }}); + } + 0x3e: decode FP_TRAPMODE { + 0,7: cvtqt({{ Fc = Fb_sq; }}); + } + } + } + } + } + + // misc FP operate + 0x17: decode FP_FULLFUNC { + format BasicOperateWithNopCheck { + 0x010: cvtlq({{ + Fc_sl = (Fb_uq<63:62> << 30) | Fb_uq<58:29>; + }}); + 0x030: cvtql({{ + Fc_uq = (Fb_uq<31:30> << 62) | (Fb_uq<29:0> << 29); + }}); + + // We treat the precise & imprecise trapping versions of + // cvtql identically. + 0x130, 0x530: cvtqlv({{ + // To avoid overflow, all the upper 32 bits must match + // the sign bit of the lower 32. We code this as + // checking the upper 33 bits for all 0s or all 1s. + uint64_t sign_bits = Fb_uq<63:31>; + if (sign_bits != 0 && sign_bits != mask(33)) + fault = new IntegerOverflowFault; + Fc_uq = (Fb_uq<31:30> << 62) | (Fb_uq<29:0> << 29); + }}); + + 0x020: cpys({{ // copy sign + Fc_uq = (Fa_uq<63:> << 63) | Fb_uq<62:0>; + }}); + 0x021: cpysn({{ // copy sign negated + Fc_uq = (~Fa_uq<63:> << 63) | Fb_uq<62:0>; + }}); + 0x022: cpyse({{ // copy sign and exponent + Fc_uq = (Fa_uq<63:52> << 52) | Fb_uq<51:0>; + }}); + + 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }}); + 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }}); + 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }}); + 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }}); + 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }}); + 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }}); + + 0x024: mt_fpcr({{ FPCR = Fa_uq; }}, IsIprAccess); + 0x025: mf_fpcr({{ Fa_uq = FPCR; }}, IsIprAccess); + } + } + + // miscellaneous mem-format ops + 0x18: decode MEMFUNC { + format WarnUnimpl { + 0x8000: fetch(); + 0xa000: fetch_m(); + 0xe800: ecb(); + } + + format MiscPrefetch { + 0xf800: wh64({{ EA = Rb & ~ULL(63); }}, + {{ ; }}, + mem_flags = PREFETCH); + } + + format BasicOperate { + 0xc000: rpcc({{ + /* Rb is a fake dependency so here is a fun way to get + * the parser to understand that. + */ + uint64_t unused_var M5_VAR_USED = Rb; + Ra = FullSystem ? xc->readMiscReg(IPR_CC) : curTick(); + }}, IsUnverifiable); + + // All of the barrier instructions below do nothing in + // their execute() methods (hence the empty code blocks). + // All of their functionality is hard-coded in the + // pipeline based on the flags IsSerializing, + // IsMemBarrier, and IsWriteBarrier. In the current + // detailed CPU model, the execute() function only gets + // called at fetch, so there's no way to generate pipeline + // behavior at any other stage. Once we go to an + // exec-in-exec CPU model we should be able to get rid of + // these flags and implement this behavior via the + // execute() methods. + + // trapb is just a barrier on integer traps, where excb is + // a barrier on integer and FP traps. "EXCB is thus a + // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat + // them the same though. + 0x0000: trapb({{ }}, IsSerializing, IsSerializeBefore, No_OpClass); + 0x0400: excb({{ }}, IsSerializing, IsSerializeBefore, No_OpClass); + 0x4000: mb({{ }}, IsMemBarrier, MemReadOp); + 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp); + } + + 0xe000: decode FullSystemInt { + 0: FailUnimpl::rc_se(); + default: BasicOperate::rc({{ + Ra = IntrFlag; + IntrFlag = 0; + }}, IsNonSpeculative, IsUnverifiable); + } + 0xf000: decode FullSystemInt { + 0: FailUnimpl::rs_se(); + default: BasicOperate::rs({{ + Ra = IntrFlag; + IntrFlag = 1; + }}, IsNonSpeculative, IsUnverifiable); + } + } + + 0x00: decode FullSystemInt { + 0: decode PALFUNC { + format EmulatedCallPal { + 0x00: halt ({{ + exitSimLoop("halt instruction encountered"); + }}, IsNonSpeculative); + 0x83: callsys({{ + xc->syscall(R0); + }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); + // Read uniq reg into ABI return value register (r0) + 0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess); + // Write uniq reg with value from ABI arg register (r16) + 0x9f: wruniq({{ Runiq = R16; }}, IsIprAccess); + } + } + default: CallPal::call_pal({{ + if (!palValid || + (palPriv + && xc->readMiscReg(IPR_ICM) != mode_kernel)) { + // invalid pal function code, or attempt to do privileged + // PAL call in non-kernel mode + fault = new UnimplementedOpcodeFault; + } else { + // check to see if simulator wants to do something special + // on this PAL call (including maybe suppress it) + bool dopal = xc->simPalCheck(palFunc); + + if (dopal) { + xc->setMiscReg(IPR_EXC_ADDR, NPC); + NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset; + } + } + }}, IsNonSpeculative); + } + + 0x1b: decode PALMODE { + 0: OpcdecFault::hw_st_quad(); + 1: decode HW_LDST_QUAD { + format HwLoad { + 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem_ul; }}, + L, IsSerializing, IsSerializeBefore); + 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem_uq; }}, + Q, IsSerializing, IsSerializeBefore); + } + } + } + + 0x1f: decode PALMODE { + 0: OpcdecFault::hw_st_cond(); + format HwStore { + 1: decode HW_LDST_COND { + 0: decode HW_LDST_QUAD { + 0: hw_st({{ EA = (Rb + disp) & ~3; }}, + {{ Mem_ul = Ra<31:0>; }}, L, IsSerializing, IsSerializeBefore); + 1: hw_st({{ EA = (Rb + disp) & ~7; }}, + {{ Mem_uq = Ra_uq; }}, Q, IsSerializing, IsSerializeBefore); + } + + 1: FailUnimpl::hw_st_cond(); + } + } + } + + 0x19: decode PALMODE { + 0: OpcdecFault::hw_mfpr(); + format HwMoveIPR { + 1: hw_mfpr({{ + int miscRegIndex = (ipr_index < MaxInternalProcRegs) ? + IprToMiscRegIndex[ipr_index] : -1; + if(miscRegIndex < 0 || !IprIsReadable(miscRegIndex) || + miscRegIndex >= NumInternalProcRegs) + fault = new UnimplementedOpcodeFault; + else + Ra = xc->readMiscReg(miscRegIndex); + }}, IsIprAccess); + } + } + + 0x1d: decode PALMODE { + 0: OpcdecFault::hw_mtpr(); + format HwMoveIPR { + 1: hw_mtpr({{ + int miscRegIndex = (ipr_index < MaxInternalProcRegs) ? + IprToMiscRegIndex[ipr_index] : -1; + if(miscRegIndex < 0 || !IprIsWritable(miscRegIndex) || + miscRegIndex >= NumInternalProcRegs) + fault = new UnimplementedOpcodeFault; + else + xc->setMiscReg(miscRegIndex, Ra); + if (traceData) { traceData->setData(Ra); } + }}, IsIprAccess); + } + } + + 0x1e: decode PALMODE { + 0: OpcdecFault::hw_rei(); + format BasicOperate { + 1: hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); + } + } + + format BasicOperate { + // M5 special opcodes use the reserved 0x01 opcode space + 0x01: decode M5FUNC { + 0x00: arm({{ + PseudoInst::arm(xc->tcBase()); + }}, IsNonSpeculative); + 0x01: quiesce({{ + PseudoInst::quiesce(xc->tcBase()); + }}, IsNonSpeculative, IsQuiesce); + 0x02: quiesceNs({{ + PseudoInst::quiesceNs(xc->tcBase(), R16); + }}, IsNonSpeculative, IsQuiesce); + 0x03: quiesceCycles({{ + PseudoInst::quiesceCycles(xc->tcBase(), R16); + }}, IsNonSpeculative, IsQuiesce, IsUnverifiable); + 0x04: quiesceTime({{ + R0 = PseudoInst::quiesceTime(xc->tcBase()); + }}, IsNonSpeculative, IsUnverifiable); + 0x07: rpns({{ + R0 = PseudoInst::rpns(xc->tcBase()); + }}, IsNonSpeculative, IsUnverifiable); + 0x09: wakeCPU({{ + PseudoInst::wakeCPU(xc->tcBase(), R16); + }}, IsNonSpeculative, IsUnverifiable); + 0x10: deprecated_ivlb({{ + warn_once("Obsolete M5 ivlb instruction encountered.\n"); + }}); + 0x11: deprecated_ivle({{ + warn_once("Obsolete M5 ivlb instruction encountered.\n"); + }}); + 0x20: deprecated_exit ({{ + warn_once("deprecated M5 exit instruction encountered.\n"); + PseudoInst::m5exit(xc->tcBase(), 0); + }}, No_OpClass, IsNonSpeculative); + 0x21: m5exit({{ + PseudoInst::m5exit(xc->tcBase(), R16); + }}, No_OpClass, IsNonSpeculative); + 0x31: loadsymbol({{ + PseudoInst::loadsymbol(xc->tcBase()); + }}, No_OpClass, IsNonSpeculative); + 0x30: initparam({{ + Ra = PseudoInst::initParam(xc->tcBase()); + }}); + 0x40: resetstats({{ + PseudoInst::resetstats(xc->tcBase(), R16, R17); + }}, IsNonSpeculative); + 0x41: dumpstats({{ + PseudoInst::dumpstats(xc->tcBase(), R16, R17); + }}, IsNonSpeculative); + 0x42: dumpresetstats({{ + PseudoInst::dumpresetstats(xc->tcBase(), R16, R17); + }}, IsNonSpeculative); + 0x43: m5checkpoint({{ + PseudoInst::m5checkpoint(xc->tcBase(), R16, R17); + }}, IsNonSpeculative); + 0x50: m5readfile({{ + R0 = PseudoInst::readfile(xc->tcBase(), R16, R17, R18); + }}, IsNonSpeculative); + 0x51: m5break({{ + PseudoInst::debugbreak(xc->tcBase()); + }}, IsNonSpeculative); + 0x52: m5switchcpu({{ + PseudoInst::switchcpu(xc->tcBase()); + }}, IsNonSpeculative); + 0x53: m5addsymbol({{ + PseudoInst::addsymbol(xc->tcBase(), R16, R17); + }}, IsNonSpeculative); + 0x54: m5panic({{ + panic("M5 panic instruction called at pc = %#x.", PC); + }}, IsNonSpeculative); +#define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase()) + 0x55: decode RA { + 0x00: m5a_old({{ + panic("Deprecated M5 annotate instruction executed " + "at pc = %#x\n", PC); + }}, IsNonSpeculative); + 0x01: m5a_bsm({{ + CPANN(swSmBegin); + }}, IsNonSpeculative); + 0x02: m5a_esm({{ + CPANN(swSmEnd); + }}, IsNonSpeculative); + 0x03: m5a_begin({{ + CPANN(swExplictBegin); + }}, IsNonSpeculative); + 0x04: m5a_end({{ + CPANN(swEnd); + }}, IsNonSpeculative); + 0x06: m5a_q({{ + CPANN(swQ); + }}, IsNonSpeculative); + 0x07: m5a_dq({{ + CPANN(swDq); + }}, IsNonSpeculative); + 0x08: m5a_wf({{ + CPANN(swWf); + }}, IsNonSpeculative); + 0x09: m5a_we({{ + CPANN(swWe); + }}, IsNonSpeculative); + 0x0C: m5a_sq({{ + CPANN(swSq); + }}, IsNonSpeculative); + 0x0D: m5a_aq({{ + CPANN(swAq); + }}, IsNonSpeculative); + 0x0E: m5a_pq({{ + CPANN(swPq); + }}, IsNonSpeculative); + 0x0F: m5a_l({{ + CPANN(swLink); + }}, IsNonSpeculative); + 0x10: m5a_identify({{ + CPANN(swIdentify); + }}, IsNonSpeculative); + 0x11: m5a_getid({{ + R0 = CPANN(swGetId); + }}, IsNonSpeculative); + 0x13: m5a_scl({{ + CPANN(swSyscallLink); + }}, IsNonSpeculative); + 0x14: m5a_rq({{ + CPANN(swRq); + }}, IsNonSpeculative); + } // M5 Annotate Operations +#undef CPANN + 0x56: m5reserved2({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + 0x57: m5reserved3({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + 0x58: m5reserved4({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + 0x59: m5reserved5({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + } + } +} diff --git a/simulators/gem5/src/arch/alpha/isa/fp.isa b/simulators/gem5/src/arch/alpha/isa/fp.isa new file mode 100644 index 00000000..5821ebcc --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/fp.isa @@ -0,0 +1,305 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Floating-point instructions +// +// Note that many FP-type instructions which do not support all the +// various rounding & trapping modes use the simpler format +// BasicOperateWithNopCheck. +// + +output exec {{ + /// Check "FP enabled" machine status bit. Called when executing any FP + /// instruction in full-system mode. + /// @retval Full-system mode: NoFault if FP is enabled, FenFault + /// if not. Non-full-system mode: always returns NoFault. + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + Fault fault = NoFault; // dummy... this ipr access should not fault + if (FullSystem && !ICSR_FPE(xc->readMiscReg(IPR_ICSR))) { + fault = new FloatEnableFault; + } + return fault; + } +}}; + +output header {{ + /** + * Base class for general floating-point instructions. Includes + * support for various Alpha rounding and trapping modes. Only FP + * instructions that require this support are derived from this + * class; the rest derive directly from AlphaStaticInst. + */ + class AlphaFP : public AlphaStaticInst + { + public: + /// Alpha FP rounding modes. + enum RoundingMode { + Chopped = 0, ///< round toward zero + Minus_Infinity = 1, ///< round toward minus infinity + Normal = 2, ///< round to nearest (default) + Dynamic = 3, ///< use FPCR setting (in instruction) + Plus_Infinity = 3 ///< round to plus inifinity (in FPCR) + }; + + /// Alpha FP trapping modes. + /// For instructions that produce integer results, the + /// "Underflow Enable" modes really mean "Overflow Enable", and + /// the assembly modifier is V rather than U. + enum TrappingMode { + /// default: nothing enabled + Imprecise = 0, ///< no modifier + /// underflow/overflow traps enabled, inexact disabled + Underflow_Imprecise = 1, ///< /U or /V + Underflow_Precise = 5, ///< /SU or /SV + /// underflow/overflow and inexact traps enabled + Underflow_Inexact_Precise = 7 ///< /SUI or /SVI + }; + + protected: + /// Map Alpha rounding mode to C99 constants from . + static const int alphaToC99RoundingMode[]; + + /// Map enum RoundingMode values to disassembly suffixes. + static const char *roundingModeSuffix[]; + /// Map enum TrappingMode values to FP disassembly suffixes. + static const char *fpTrappingModeSuffix[]; + /// Map enum TrappingMode values to integer disassembly suffixes. + static const char *intTrappingModeSuffix[]; + + /// This instruction's rounding mode. + RoundingMode roundingMode; + /// This instruction's trapping mode. + TrappingMode trappingMode; + + /// Have we warned about this instruction's unsupported + /// rounding mode (if applicable)? + mutable bool warnedOnRounding; + + /// Have we warned about this instruction's unsupported + /// trapping mode (if applicable)? + mutable bool warnedOnTrapping; + + /// Constructor + AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass), + roundingMode((enum RoundingMode)FP_ROUNDMODE), + trappingMode((enum TrappingMode)FP_TRAPMODE), + warnedOnRounding(false), + warnedOnTrapping(false) + { + } + + int getC99RoundingMode(uint64_t fpcr_val) const; + + // This differs from the AlphaStaticInst version only in + // printing suffixes for non-default rounding & trapping modes. + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + + +output decoder {{ + int + AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const + { + if (roundingMode == Dynamic) { + return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)]; + } + else { + return alphaToC99RoundingMode[roundingMode]; + } + } + + std::string + AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::string mnem_str(mnemonic); + +#ifndef SS_COMPATIBLE_DISASSEMBLY + std::string suffix(""); + suffix += ((_destRegIdx[0] >= FP_Base_DepTag) + ? fpTrappingModeSuffix[trappingMode] + : intTrappingModeSuffix[trappingMode]); + suffix += roundingModeSuffix[roundingMode]; + + if (suffix != "") { + mnem_str = csprintf("%s/%s", mnemonic, suffix); + } +#endif + + std::stringstream ss; + ccprintf(ss, "%-10s ", mnem_str.c_str()); + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + if (_numSrcRegs > 1) { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + // just print the first dest... if there's a second one, + // it's generally implicit + if (_numDestRegs > 0) { + if (_numSrcRegs > 0) + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } + + const int AlphaFP::alphaToC99RoundingMode[] = { + M5_FE_TOWARDZERO, // Chopped + M5_FE_DOWNWARD, // Minus_Infinity + M5_FE_TONEAREST, // Normal + M5_FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR + }; + + const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" }; + // mark invalid trapping modes, but don't fail on them, because + // you could decode anything on a misspeculated path + const char *AlphaFP::fpTrappingModeSuffix[] = + { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" }; + const char *AlphaFP::intTrappingModeSuffix[] = + { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" }; +}}; + +// FP instruction class execute method template. Handles non-standard +// rounding modes. +def template FloatingPointExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (trappingMode != Imprecise && !warnedOnTrapping) { + warn("%s: non-standard trapping mode not supported", + generateDisassembly(0, NULL)); + warnedOnTrapping = true; + } + + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; +#if USE_FENV + if (roundingMode == Normal) { + %(code)s; + } else { + m5_fesetround(getC99RoundingMode( + xc->readMiscReg(MISCREG_FPCR))); + %(code)s; + m5_fesetround(M5_FE_TONEAREST); + } +#else + if (roundingMode != Normal && !warnedOnRounding) { + warn("%s: non-standard rounding mode not supported", + generateDisassembly(0, NULL)); + warnedOnRounding = true; + } + %(code)s; +#endif + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +// FP instruction class execute method template where no dynamic +// rounding mode control is needed. Like BasicExecute, but includes +// check & warning for non-standard trapping mode. +def template FPFixedRoundingExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (trappingMode != Imprecise && !warnedOnTrapping) { + warn("%s: non-standard trapping mode not supported", + generateDisassembly(0, NULL)); + warnedOnTrapping = true; + } + + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template FloatingPointDecode {{ + { + AlphaStaticInst *i = new %(class_name)s(machInst); + if (FC == 31) { + i = makeNop(i); + } + return i; + } +}}; + +// General format for floating-point operate instructions: +// - Checks trapping and rounding mode flags. Trapping modes +// currently unimplemented (will fail). +// - Generates NOP if FC == 31. +def format FloatingPointOperate(code, *opt_args) {{ + iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args) + decode_block = FloatingPointDecode.subst(iop) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = FloatingPointExecute.subst(iop) +}}; + +// Special format for cvttq where rounding mode is pre-decoded +def format FPFixedRounding(code, class_suffix, *opt_args) {{ + Name += class_suffix + iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args) + decode_block = FloatingPointDecode.subst(iop) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = FPFixedRoundingExecute.subst(iop) +}}; + diff --git a/simulators/gem5/src/arch/alpha/isa/int.isa b/simulators/gem5/src/arch/alpha/isa/int.isa new file mode 100644 index 00000000..265b3c4a --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/int.isa @@ -0,0 +1,133 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Integer operate instructions +// + +output header {{ + /** + * Base class for integer immediate instructions. + */ + class IntegerImm : public AlphaStaticInst + { + protected: + /// Immediate operand value (unsigned 8-bit int). + uint8_t imm; + + /// Constructor + IntegerImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first source reg... if there's + // a second one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + + ss << (int)imm; + + if (_numDestRegs > 0) { + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } +}}; + + +def template RegOrImmDecode {{ + { + AlphaStaticInst *i = + (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst) + : (AlphaStaticInst *)new %(class_name)s(machInst); + if (RC == 31) { + i = makeNop(i); + } + return i; + } +}}; + +// Primary format for integer operate instructions: +// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used. +// - Generates NOP if RC == 31. +def format IntegerOperate(code, *opt_flags) {{ + # If the code block contains 'Rb_or_imm', we define two instructions, + # one using 'Rb' and one using 'imm', and have the decoder select + # the right one. + uses_imm = (code.find('Rb_or_imm') != -1) + if uses_imm: + orig_code = code + # base code is reg version: + # rewrite by substituting 'Rb' for 'Rb_or_imm' + code = re.sub(r'Rb_or_imm', 'Rb', orig_code) + # generate immediate version by substituting 'imm' + # note that imm takes no extenstion, so we extend + # the regexp to replace any extension as well + imm_code = re.sub(r'Rb_or_imm(_\w+)?', 'imm', orig_code) + + # generate declaration for register version + iop = InstObjParams(name, Name, 'AlphaStaticInst', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = BasicExecute.subst(iop) + + if uses_imm: + # append declaration for imm version + imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_code, + opt_flags) + header_output += BasicDeclare.subst(imm_iop) + decoder_output += BasicConstructor.subst(imm_iop) + exec_output += BasicExecute.subst(imm_iop) + # decode checks IMM bit to pick correct version + decode_block = RegOrImmDecode.subst(iop) + else: + # no imm version: just check for nop + decode_block = OperateNopCheckDecode.subst(iop) +}}; diff --git a/simulators/gem5/src/arch/alpha/isa/main.isa b/simulators/gem5/src/arch/alpha/isa/main.isa new file mode 100644 index 00000000..cb43c135 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/main.isa @@ -0,0 +1,477 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Alpha ISA description file. +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// +// Output include file directives. +// + +output header {{ +#include +#include +#include + +#include "arch/alpha/faults.hh" +#include "arch/alpha/types.hh" +#include "config/ss_compatible_fp.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/request.hh" // some constructors use MemReq flags +}}; + +output decoder {{ +#include + +#include "arch/alpha/decoder.hh" +#include "arch/alpha/registers.hh" +#include "arch/alpha/regredir.hh" +#include "base/loader/symtab.hh" +#include "base/cprintf.hh" +#include "base/fenv.hh" +#include "config/ss_compatible_fp.hh" +#include "cpu/thread_context.hh" // for Jump::branchTarget() +#include "mem/packet.hh" +#include "sim/full_system.hh" + +using namespace AlphaISA; +}}; + +output exec {{ +#include + +#include "arch/alpha/decoder.hh" +#include "arch/alpha/registers.hh" +#include "arch/alpha/regredir.hh" +#include "arch/generic/memhelpers.hh" +#include "base/cp_annotate.hh" +#include "base/fenv.hh" +#include "config/ss_compatible_fp.hh" +#include "cpu/base.hh" +#include "cpu/exetrace.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/full_system.hh" +#include "sim/pseudo_inst.hh" +#include "sim/sim_exit.hh" + +using namespace AlphaISA; +}}; + +//////////////////////////////////////////////////////////////////// +// +// Namespace statement. Everything below this line will be in the +// AlphaISAInst namespace. +// + + +namespace AlphaISA; + +//////////////////////////////////////////////////////////////////// +// +// Bitfield definitions. +// + +// Universal (format-independent) fields +def bitfield PALMODE <32:32>; +def bitfield OPCODE <31:26>; +def bitfield RA <25:21>; +def bitfield RB <20:16>; + +// Memory format +def signed bitfield MEMDISP <15: 0>; // displacement +def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned) + +// Memory-format jumps +def bitfield JMPFUNC <15:14>; // function code (disp<15:14>) +def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>) + +// Branch format +def signed bitfield BRDISP <20: 0>; // displacement + +// Integer operate format(s>; +def bitfield INTIMM <20:13>; // integer immediate (literal) +def bitfield IMM <12:12>; // immediate flag +def bitfield INTFUNC <11: 5>; // function code +def bitfield RC < 4: 0>; // dest reg + +// Floating-point operate format +def bitfield FA <25:21>; +def bitfield FB <20:16>; +def bitfield FP_FULLFUNC <15: 5>; // complete function code + def bitfield FP_TRAPMODE <15:13>; // trapping mode + def bitfield FP_ROUNDMODE <12:11>; // rounding mode + def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding + def bitfield FP_SRCTYPE <10: 9>; // source reg type + def bitfield FP_SHORTFUNC < 8: 5>; // short function code + def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code +def bitfield FC < 4: 0>; // dest reg + +// PALcode format +def bitfield PALFUNC <25: 0>; // function code + +// EV5 PAL instructions: +// HW_LD/HW_ST +def bitfield HW_LDST_PHYS <15>; // address is physical +def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR +def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc +def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b +def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch +def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked +def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional +def signed bitfield HW_LDST_DISP <9:0>; // signed displacement + +// HW_REI +def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk +def bitfield HW_REI_MBZ <13: 0>; // must be zero + +// HW_MTPR/MW_MFPR +def bitfield HW_IPR_IDX <15:0>; // IPR index + +// M5 instructions +def bitfield M5FUNC <7:0>; + +def operand_types {{ + 'sb' : 'int8_t', + 'ub' : 'uint8_t', + 'sw' : 'int16_t', + 'uw' : 'uint16_t', + 'sl' : 'int32_t', + 'ul' : 'uint32_t', + 'sq' : 'int64_t', + 'uq' : 'uint64_t', + 'sf' : 'float', + 'df' : 'double' +}}; + +def operands {{ + # Int regs default to unsigned, but code should not count on this. + # For clarity, descriptions that depend on unsigned behavior should + # explicitly specify '_uq'. + 'Ra': ('IntReg', 'uq', 'PALMODE ? reg_redir[RA] : RA', + 'IsInteger', 1), + 'Rb': ('IntReg', 'uq', 'PALMODE ? reg_redir[RB] : RB', + 'IsInteger', 2), + 'Rc': ('IntReg', 'uq', 'PALMODE ? reg_redir[RC] : RC', + 'IsInteger', 3), + 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), + 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), + 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), + 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + 'PC': ('PCState', 'uq', 'pc', ( None, None, 'IsControl' ), 4), + 'NPC': ('PCState', 'uq', 'npc', ( None, None, 'IsControl' ), 4), + 'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1), + 'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1), + 'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1), + # The next two are hacks for non-full-system call-pal emulation + 'R0': ('IntReg', 'uq', '0', None, 1), + 'R16': ('IntReg', 'uq', '16', None, 1), + 'R17': ('IntReg', 'uq', '17', None, 1), + 'R18': ('IntReg', 'uq', '18', None, 1) +}}; + +//////////////////////////////////////////////////////////////////// +// +// Basic instruction classes/templates/formats etc. +// + +output header {{ +// uncomment the following to get SimpleScalar-compatible disassembly +// (useful for diffing output traces). +// #define SS_COMPATIBLE_DISASSEMBLY + + /** + * Base class for all Alpha static instructions. + */ + class AlphaStaticInst : public StaticInst + { + protected: + + /// Make AlphaISA register dependence tags directly visible in + /// this class and derived classes. Maybe these should really + /// live here and not in the AlphaISA namespace. + enum DependenceTags { + FP_Base_DepTag = AlphaISA::FP_Base_DepTag + }; + + /// Constructor. + AlphaStaticInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + /// Print a register name for disassembly given the unique + /// dependence tag number (FP or int). + void printReg(std::ostream &os, int reg) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + void + advancePC(AlphaISA::PCState &pcState) const + { + pcState.advance(); + } + }; +}}; + +output decoder {{ + void + AlphaStaticInst::printReg(std::ostream &os, int reg) const + { + if (reg < FP_Base_DepTag) { + ccprintf(os, "r%d", reg); + } + else { + ccprintf(os, "f%d", reg - FP_Base_DepTag); + } + } + + std::string + AlphaStaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + if (_numSrcRegs > 1) { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + // just print the first dest... if there's a second one, + // it's generally implicit + if (_numDestRegs > 0) { + if (_numSrcRegs > 0) + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } +}}; + +// Declarations for execute() methods. +def template BasicExecDeclare {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +// Basic instruction class declaration template. +def template BasicDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + /// Constructor. + %(class_name)s(ExtMachInst machInst); + + %(BasicExecDeclare)s + }; +}}; + +// Basic instruction class constructor template. +def template BasicConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + +// Basic instruction class execute method template. +def template BasicExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +// Basic decode template. +def template BasicDecode {{ + return new %(class_name)s(machInst); +}}; + +// Basic decode template, passing mnemonic in as string arg to constructor. +def template BasicDecodeWithMnemonic {{ + return new %(class_name)s("%(mnemonic)s", machInst); +}}; + +// The most basic instruction format... used only for a few misc. insts +def format BasicOperate(code, *flags) {{ + iop = InstObjParams(name, Name, 'AlphaStaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + + +//////////////////////////////////////////////////////////////////// +// +// Nop +// + +output header {{ + /** + * Static instruction class for no-ops. This is a leaf class. + */ + class Nop : public AlphaStaticInst + { + /// Disassembly of original instruction. + const std::string originalDisassembly; + + public: + /// Constructor + Nop(const std::string _originalDisassembly, ExtMachInst _machInst) + : AlphaStaticInst("nop", _machInst, No_OpClass), + originalDisassembly(_originalDisassembly) + { + flags[IsNop] = true; + } + + ~Nop() { } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + %(BasicExecDeclare)s + }; + + /// Helper function for decoding nops. Substitute Nop object + /// for original inst passed in as arg (and delete latter). + static inline + AlphaStaticInst * + makeNop(AlphaStaticInst *inst) + { + AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); + delete inst; + return nop; + } +}}; + +output decoder {{ + std::string Nop::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return originalDisassembly; +#else + return csprintf("%-10s (%s)", "nop", originalDisassembly); +#endif + } +}}; + +output exec {{ + Fault + Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + return NoFault; + } +}}; + +// integer & FP operate instructions use Rc as dest, so check for +// Rc == 31 to detect nops +def template OperateNopCheckDecode {{ + { + AlphaStaticInst *i = new %(class_name)s(machInst); + if (RC == 31) { + i = makeNop(i); + } + return i; + } +}}; + +// Like BasicOperate format, but generates NOP if RC/FC == 31 +def format BasicOperateWithNopCheck(code, *opt_args) {{ + iop = InstObjParams(name, Name, 'AlphaStaticInst', code, opt_args) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +// Integer instruction templates, formats, etc. +##include "int.isa" + +// Floating-point instruction templates, formats, etc. +##include "fp.isa" + +// Memory instruction templates, formats, etc. +##include "mem.isa" + +// Branch/jump instruction templates, formats, etc. +##include "branch.isa" + +// PAL instruction templates, formats, etc. +##include "pal.isa" + +// Opcdec fault instruction templates, formats, etc. +##include "opcdec.isa" + +// Unimplemented instruction templates, formats, etc. +##include "unimp.isa" + +// Unknown instruction templates, formats, etc. +##include "unknown.isa" + +// Execution utility functions +##include "util.isa" + +// The actual decoder +##include "decoder.isa" diff --git a/simulators/gem5/src/arch/alpha/isa/mem.isa b/simulators/gem5/src/arch/alpha/isa/mem.isa new file mode 100644 index 00000000..f286be91 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/mem.isa @@ -0,0 +1,573 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt +// Kevin Lim + +//////////////////////////////////////////////////////////////////// +// +// Memory-format instructions: LoadAddress, Load, Store +// + +output header {{ + /** + * Base class for general Alpha memory-format instructions. + */ + class Memory : public AlphaStaticInst + { + protected: + + /// Memory request flags. See mem_req_base.hh. + Request::Flags memAccessFlags; + + /// Constructor + Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for memory-format instructions using a 32-bit + * displacement (i.e. most of them). + */ + class MemoryDisp32 : public Memory + { + protected: + /// Displacement for EA calculation (signed). + int32_t disp; + + /// Constructor. + MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : Memory(mnem, _machInst, __opClass), + disp(MEMDISP) + { + } + }; + + + /** + * Base class for a few miscellaneous memory-format insts + * that don't interpret the disp field: wh64, fetch, fetch_m, ecb. + * None of these instructions has a destination register either. + */ + class MemoryNoDisp : public Memory + { + protected: + /// Constructor + MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : Memory(mnem, _machInst, __opClass) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + + +output decoder {{ + std::string + Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s %c%d,%d(r%d)", mnemonic, + flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB); + } + + std::string + MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (r%d)", mnemonic, RB); + } +}}; + +def format LoadAddress(code) {{ + iop = InstObjParams(name, Name, 'MemoryDisp32', code) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst); + + %(BasicExecDeclare)s + + %(EACompDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + + +def template EACompDeclare {{ + Fault eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, + Trace::InstRecord *) const; +}}; + +def template LoadStoreConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + +def template EACompExecute {{ + Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(op_wb)s; + xc->setEA(EA); + } + + return fault; + } +}}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = readMemTiming(xc, traceData, EA, Mem, memAccessFlags); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + + getMem(pkt, Mem, traceData); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = writeMemAtomic(xc, traceData, Mem, EA, + memAccessFlags, NULL); + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = writeMemAtomic(xc, traceData, Mem, EA, + memAccessFlags, &write_result); + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = writeMemTiming(xc, traceData, Mem, EA, + memAccessFlags, NULL); + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return NoFault; + } +}}; + + +def template StoreCondCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + uint64_t write_result = pkt->req->getExtraData(); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template MiscExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA M5_VAR_USED; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + warn_once("Prefetch instructions in Alpha do not do anything\n"); + if (fault == NoFault) { + %(memacc_code)s; + } + + return NoFault; + } +}}; + +// Prefetches in Alpha don't actually do anything +// They just build an effective address and complete +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + warn("initiateAcc undefined: Misc instruction does not support split " + "access method!"); + return NoFault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + warn("completeAcc undefined: Misc instruction does not support split " + "access method!"); + + return NoFault; + } +}}; + + +// load instructions use Ra as dest, so check for +// Ra == 31 to detect nops +def template LoadNopCheckDecode {{ + { + AlphaStaticInst *i = new %(class_name)s(machInst); + if (RA == 31) { + i = makeNop(i); + } + return i; + } +}}; + + +// for some load instructions, Ra == 31 indicates a prefetch (not a nop) +def template LoadPrefetchCheckDecode {{ + { + if (RA != 31) { + return new %(class_name)s(machInst); + } + else { + return new %(class_name)sPrefetch(machInst); + } + } +}}; + + +let {{ +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code = '', base_class = 'MemoryDisp32', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # Some CPU models execute the memory operation as an atomic unit, + # while others want to separate them into an effective address + # computation and a memory access operation. As a result, we need + # to generate three StaticInst objects. Note that the latter two + # are nested inside the larger "atomic" one. + + # Generate InstObjParams for each of the three objects. Note that + # they differ only in the set of code objects contained (which in + # turn affects the object's overall operand list). + iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + memacc_iop = InstObjParams(name, Name, base_class, + { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + + if mem_flags: + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + memacc_iop.constructor += s + + # select templates + + # The InitiateAcc template is the same for StoreCond templates as the + # corresponding Store template.. + StoreCondInitiateAcc = StoreInitiateAcc + + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), + LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + fullExecTemplate.subst(iop) + + EACompExecute.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) +}}; + +def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +// Note that the flags passed in apply only to the prefetch version +def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, + mem_flags = [], pf_flags = [], inst_flags = []) {{ + # declare the load instruction object and generate the decode block + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadPrefetchCheckDecode, + exec_template_base = 'Load') + + # Declare the prefetch instruction object. + + # Make sure flag args are lists so we can mess with them. + mem_flags = makeList(mem_flags) + pf_flags = makeList(pf_flags) + inst_flags = makeList(inst_flags) + + pf_mem_flags = mem_flags + pf_flags + ['PREFETCH'] + pf_inst_flags = inst_flags + + (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ + LoadStoreBase(name, Name + 'Prefetch', ea_code, ';', + pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') + + header_output += pf_header_output + decoder_output += pf_decoder_output + exec_output += pf_exec_output +}}; + + +def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + + +def format StoreCond(memacc_code, postacc_code, + ea_code = {{ EA = Rb + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code, exec_template_base = 'StoreCond') +}}; + + +// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb +def format MiscPrefetch(ea_code, memacc_code, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = 'MemoryNoDisp', exec_template_base = 'Misc') +}}; + + diff --git a/simulators/gem5/src/arch/alpha/isa/opcdec.isa b/simulators/gem5/src/arch/alpha/isa/opcdec.isa new file mode 100644 index 00000000..d279ae05 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/opcdec.isa @@ -0,0 +1,79 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Kevin Lim + +//////////////////////////////////////////////////////////////////// +// +// OPCDEC fault instructions +// + +output header {{ + /** + * Static instruction class for instructions that cause an OPCDEC fault + * when executed. This is currently only for PAL mode instructions + * executed in non-PAL mode. + */ + class OpcdecFault : public AlphaStaticInst + { + public: + /// Constructor + OpcdecFault(ExtMachInst _machInst) + : AlphaStaticInst("opcdec fault", _machInst, No_OpClass) + { + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + OpcdecFault::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x)", + " OPCDEC fault", machInst, OPCODE); + } +}}; + +output exec {{ + Fault + OpcdecFault::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return new UnimplementedOpcodeFault; + } +}}; + +def format OpcdecFault() {{ + decode_block = 'return new OpcdecFault(machInst);\n' +}}; + diff --git a/simulators/gem5/src/arch/alpha/isa/pal.isa b/simulators/gem5/src/arch/alpha/isa/pal.isa new file mode 100644 index 00000000..53e0d619 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/pal.isa @@ -0,0 +1,274 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// PAL calls & PAL-specific instructions +// + +output header {{ + /** + * Base class for emulated call_pal calls (used only in + * non-full-system mode). + */ + class EmulatedCallPal : public AlphaStaticInst + { + protected: + + /// Constructor. + EmulatedCallPal(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + EmulatedCallPal::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%s %s", "call_pal", mnemonic); +#else + return csprintf("%-10s %s", "call_pal", mnemonic); +#endif + } +}}; + +def format EmulatedCallPal(code, *flags) {{ + iop = InstObjParams(name, Name, 'EmulatedCallPal', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +output header {{ + /** + * Base class for full-system-mode call_pal instructions. + * Probably could turn this into a leaf class and get rid of the + * parser template. + */ + class CallPalBase : public AlphaStaticInst + { + protected: + int palFunc; ///< Function code part of instruction + int palOffset; ///< Target PC, offset from IPR_PAL_BASE + bool palValid; ///< is the function code valid? + bool palPriv; ///< is this call privileged? + + /// Constructor. + CallPalBase(const char *mnem, ExtMachInst _machInst, + OpClass __opClass); + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + inline + CallPalBase::CallPalBase(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass), + palFunc(PALFUNC) + { + // From the 21164 HRM (paraphrased): + // Bit 7 of the function code (mask 0x80) indicates + // whether the call is privileged (bit 7 == 0) or + // unprivileged (bit 7 == 1). The privileged call table + // starts at 0x2000, the unprivielged call table starts at + // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the + // offset. + const int palPrivMask = 0x80; + const int palOffsetMask = 0x3f; + + // Pal call is invalid unless all other bits are 0 + palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0); + palPriv = ((machInst & palPrivMask) == 0); + int shortPalFunc = (machInst & palOffsetMask); + // Add 1 to base to set pal-mode bit + palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6); + } + + std::string + CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s %#x", "call_pal", palFunc); + } +}}; + +def format CallPal(code, *flags) {{ + iop = InstObjParams(name, Name, 'CallPalBase', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +//////////////////////////////////////////////////////////////////// +// +// hw_ld, hw_st +// + +output header {{ + /** + * Base class for hw_ld and hw_st. + */ + class HwLoadStore : public Memory + { + protected: + + /// Displacement for EA calculation (signed). + int16_t disp; + + /// Constructor + HwLoadStore(const char *mnem, ExtMachInst _machInst, OpClass __opClass); + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + + +output decoder {{ + inline + HwLoadStore::HwLoadStore(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : Memory(mnem, _machInst, __opClass), disp(HW_LDST_DISP) + { + memAccessFlags.clear(); + if (HW_LDST_PHYS) memAccessFlags.set(Request::PHYSICAL); + if (HW_LDST_ALT) memAccessFlags.set(Request::ALTMODE); + if (HW_LDST_VPTE) memAccessFlags.set(Request::VPTE); + if (HW_LDST_LOCK) memAccessFlags.set(Request::LLSC); + } + + std::string + HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB); +#else + // HW_LDST_LOCK and HW_LDST_COND are the same bit. + const char *lock_str = + (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : ""; + + return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s", + mnemonic, RA, disp, RB, + HW_LDST_PHYS ? ",PHYS" : "", + HW_LDST_ALT ? ",ALT" : "", + HW_LDST_QUAD ? ",QUAD" : "", + HW_LDST_VPTE ? ",VPTE" : "", + lock_str); +#endif + } +}}; + +def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name + class_ext, ea_code, memacc_code, + mem_flags = [], inst_flags = flags, + base_class = 'HwLoadStore', exec_template_base = 'Load') +}}; + + +def format HwStore(ea_code, memacc_code, class_ext, *flags) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name + class_ext, ea_code, memacc_code, + mem_flags = [], inst_flags = flags, + base_class = 'HwLoadStore', exec_template_base = 'Store') +}}; + + +def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, + *flags) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name + class_ext, ea_code, memacc_code, + postacc_code, mem_flags = [], inst_flags = flags, + base_class = 'HwLoadStore') +}}; + + +output header {{ + /** + * Base class for hw_mfpr and hw_mtpr. + */ + class HwMoveIPR : public AlphaStaticInst + { + protected: + /// Index of internal processor register. + int ipr_index; + + /// Constructor + HwMoveIPR(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : AlphaStaticInst(mnem, _machInst, __opClass), + ipr_index(HW_IPR_IDX) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + if (_numSrcRegs > 0) { + // must be mtpr + return csprintf("%-10s r%d,IPR(%#x)", + mnemonic, RA, ipr_index); + } + else { + // must be mfpr + return csprintf("%-10s IPR(%#x),r%d", + mnemonic, ipr_index, RA); + } + } +}}; + +def format HwMoveIPR(code, *flags) {{ + all_flags = ['IprAccessOp'] + all_flags += flags + iop = InstObjParams(name, Name, 'HwMoveIPR', code, all_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + diff --git a/simulators/gem5/src/arch/alpha/isa/unimp.isa b/simulators/gem5/src/arch/alpha/isa/unimp.isa new file mode 100644 index 00000000..6cfaa699 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/unimp.isa @@ -0,0 +1,172 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Unimplemented instructions +// + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public AlphaStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst) + : AlphaStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public AlphaStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst) + : AlphaStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s", mnemonic); +#else + return csprintf("%-10s (unimplemented)", mnemonic); +#endif + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE); + return new UnimplementedOpcodeFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("instruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public AlphaStaticInst + { + public: + /// Constructor + Unknown(ExtMachInst _machInst) + : AlphaStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + diff --git a/simulators/gem5/src/arch/alpha/isa/unknown.isa b/simulators/gem5/src/arch/alpha/isa/unknown.isa new file mode 100644 index 00000000..1e95ccf6 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/unknown.isa @@ -0,0 +1,59 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Unknown instructions +// + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x)", + "unknown", machInst, OPCODE); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction " + "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); + return new UnimplementedOpcodeFault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/simulators/gem5/src/arch/alpha/isa/util.isa b/simulators/gem5/src/arch/alpha/isa/util.isa new file mode 100644 index 00000000..8700d1e0 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa/util.isa @@ -0,0 +1,119 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Utility functions for execute methods +// + +output exec {{ + + /// Return opa + opb, summing carry into third arg. + inline uint64_t + addc(uint64_t opa, uint64_t opb, int &carry) + { + uint64_t res = opa + opb; + if (res < opa || res < opb) + ++carry; + return res; + } + + /// Multiply two 64-bit values (opa * opb), returning the 128-bit + /// product in res_hi and res_lo. + inline void + mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo) + { + // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies + uint64_t opa_hi = opa<63:32>; + uint64_t opa_lo = opa<31:0>; + uint64_t opb_hi = opb<63:32>; + uint64_t opb_lo = opb<31:0>; + + res_lo = opa_lo * opb_lo; + + // The middle partial products logically belong in bit + // positions 95 to 32. Thus the lower 32 bits of each product + // sum into the upper 32 bits of the low result, while the + // upper 32 sum into the low 32 bits of the upper result. + uint64_t partial1 = opa_hi * opb_lo; + uint64_t partial2 = opa_lo * opb_hi; + + uint64_t partial1_lo = partial1<31:0> << 32; + uint64_t partial1_hi = partial1<63:32>; + uint64_t partial2_lo = partial2<31:0> << 32; + uint64_t partial2_hi = partial2<63:32>; + + // Add partial1_lo and partial2_lo to res_lo, keeping track + // of any carries out + int carry_out = 0; + res_lo = addc(partial1_lo, res_lo, carry_out); + res_lo = addc(partial2_lo, res_lo, carry_out); + + // Now calculate the high 64 bits... + res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out; + } + + /// Map 8-bit S-floating exponent to 11-bit T-floating exponent. + /// See Table 2-2 of Alpha AHB. + inline int + map_s(int old_exp) + { + int hibit = old_exp<7:>; + int lobits = old_exp<6:0>; + + if (hibit == 1) { + return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits); + } + else { + return (lobits == 0) ? 0 : (0x380 | lobits); + } + } + + /// Convert a 32-bit S-floating value to the equivalent 64-bit + /// representation to be stored in an FP reg. + inline uint64_t + s_to_t(uint32_t s_val) + { + uint64_t tmp = s_val; + return (tmp<31:> << 63 // sign bit + | (uint64_t)map_s(tmp<30:23>) << 52 // exponent + | tmp<22:0> << 29); // fraction + } + + /// Convert a 64-bit T-floating value to the equivalent 32-bit + /// S-floating representation to be stored in memory. + inline int32_t + t_to_s(uint64_t t_val) + { + return (t_val<63:62> << 30 // sign bit & hi exp bit + | t_val<58:29>); // rest of exp & fraction + } +}}; + diff --git a/simulators/gem5/src/arch/alpha/isa_traits.hh b/simulators/gem5/src/arch/alpha/isa_traits.hh new file mode 100644 index 00000000..5738ccdb --- /dev/null +++ b/simulators/gem5/src/arch/alpha/isa_traits.hh @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_ISA_TRAITS_HH__ +#define __ARCH_ALPHA_ISA_TRAITS_HH__ + +namespace LittleEndianGuest {} + +#include "arch/alpha/types.hh" +#include "base/types.hh" +#include "cpu/static_inst_fwd.hh" + +namespace AlphaISA { + +using namespace LittleEndianGuest; + +StaticInstPtr decodeInst(ExtMachInst); + +// Alpha Does NOT have a delay slot +#define ISA_HAS_DELAY_SLOT 0 + +const Addr PageShift = 13; +const Addr PageBytes = ULL(1) << PageShift; +const Addr PageMask = ~(PageBytes - 1); +const Addr PageOffset = PageBytes - 1; + +//////////////////////////////////////////////////////////////////////// +// +// Translation stuff +// + +const Addr PteShift = 3; +const Addr NPtePageShift = PageShift - PteShift; +const Addr NPtePage = ULL(1) << NPtePageShift; +const Addr PteMask = NPtePage - 1; + +// User Virtual +const Addr USegBase = ULL(0x0); +const Addr USegEnd = ULL(0x000003ffffffffff); + +// Kernel Direct Mapped +const Addr K0SegBase = ULL(0xfffffc0000000000); +const Addr K0SegEnd = ULL(0xfffffdffffffffff); + +// Kernel Virtual +const Addr K1SegBase = ULL(0xfffffe0000000000); +const Addr K1SegEnd = ULL(0xffffffffffffffff); + +//////////////////////////////////////////////////////////////////////// +// +// Interrupt levels +// +enum InterruptLevels +{ + INTLEVEL_SOFTWARE_MIN = 4, + INTLEVEL_SOFTWARE_MAX = 19, + + INTLEVEL_EXTERNAL_MIN = 20, + INTLEVEL_EXTERNAL_MAX = 34, + + INTLEVEL_IRQ0 = 20, + INTLEVEL_IRQ1 = 21, + INTINDEX_ETHERNET = 0, + INTINDEX_SCSI = 1, + INTLEVEL_IRQ2 = 22, + INTLEVEL_IRQ3 = 23, + + INTLEVEL_SERIAL = 33, + + NumInterruptLevels = INTLEVEL_EXTERNAL_MAX +}; + +// EV5 modes +enum mode_type +{ + mode_kernel = 0, // kernel + mode_executive = 1, // executive (unused by unix) + mode_supervisor = 2, // supervisor (unused by unix) + mode_user = 3, // user mode + mode_number // number of modes +}; + +// Constants Related to the number of registers + +enum { + LogVMPageSize = 13, // 8K bytes + VMPageSize = (1 << LogVMPageSize), + + BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned + + MachineBytes = 8, + WordBytes = 4, + HalfwordBytes = 2, + ByteBytes = 1 +}; + +// return a no-op instruction... used for instruction fetch faults +// Alpha UNOP (ldq_u r31,0(r0)) +const ExtMachInst NoopMachInst = 0x2ffe0000; + +// Memory accesses cannot be unaligned +const bool HasUnalignedMemAcc = false; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/simulators/gem5/src/arch/alpha/kernel_stats.cc b/simulators/gem5/src/arch/alpha/kernel_stats.cc new file mode 100644 index 00000000..c057e7f1 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/kernel_stats.cc @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Lisa Hsu + * Nathan Binkert + */ + +#include +#include +#include + +#include "arch/alpha/linux/threadinfo.hh" +#include "arch/alpha/kernel_stats.hh" +#include "arch/alpha/osfpal.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/Context.hh" +#include "kern/tru64/tru64_syscalls.hh" +#include "sim/system.hh" + +using namespace std; +using namespace Stats; + +namespace AlphaISA { +namespace Kernel { + +const char *modestr[] = { "kernel", "user", "idle" }; + +Statistics::Statistics(System *system) + : ::Kernel::Statistics(system), + idleProcess((Addr)-1), themode(kernel), lastModeTick(0) +{ +} + +void +Statistics::regStats(const string &_name) +{ + ::Kernel::Statistics::regStats(_name); + + _callpal + .init(256) + .name(name() + ".callpal") + .desc("number of callpals executed") + .flags(total | pdf | nozero | nonan) + ; + + for (int i = 0; i < PAL::NumCodes; ++i) { + const char *str = PAL::name(i); + if (str) + _callpal.subname(i, str); + } + + _hwrei + .name(name() + ".inst.hwrei") + .desc("number of hwrei instructions executed") + ; + + _mode + .init(cpu_mode_num) + .name(name() + ".mode_switch") + .desc("number of protection mode switches") + ; + + for (int i = 0; i < cpu_mode_num; ++i) + _mode.subname(i, modestr[i]); + + _modeGood + .init(cpu_mode_num) + .name(name() + ".mode_good") + ; + + for (int i = 0; i < cpu_mode_num; ++i) + _modeGood.subname(i, modestr[i]); + + _modeFraction + .name(name() + ".mode_switch_good") + .desc("fraction of useful protection mode switches") + .flags(total) + ; + + for (int i = 0; i < cpu_mode_num; ++i) + _modeFraction.subname(i, modestr[i]); + + _modeFraction = _modeGood / _mode; + + _modeTicks + .init(cpu_mode_num) + .name(name() + ".mode_ticks") + .desc("number of ticks spent at the given mode") + .flags(pdf) + ; + for (int i = 0; i < cpu_mode_num; ++i) + _modeTicks.subname(i, modestr[i]); + + _swap_context + .name(name() + ".swap_context") + .desc("number of times the context was actually changed") + ; +} + +void +Statistics::setIdleProcess(Addr idlepcbb, ThreadContext *tc) +{ + assert(themode == kernel); + idleProcess = idlepcbb; + themode = idle; + changeMode(themode, tc); +} + +void +Statistics::changeMode(cpu_mode newmode, ThreadContext *tc) +{ + _mode[newmode]++; + + if (newmode == themode) + return; + + DPRINTF(Context, "old mode=%s new mode=%s pid=%d\n", + modestr[themode], modestr[newmode], + Linux::ThreadInfo(tc).curTaskPID()); + + _modeGood[newmode]++; + _modeTicks[themode] += curTick() - lastModeTick; + + lastModeTick = curTick(); + themode = newmode; +} + +void +Statistics::mode(cpu_mode newmode, ThreadContext *tc) +{ + Addr pcbb = tc->readMiscRegNoEffect(IPR_PALtemp23); + + if (newmode == kernel && pcbb == idleProcess) + newmode = idle; + + changeMode(newmode, tc); +} + +void +Statistics::context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc) +{ + assert(themode != user); + + _swap_context++; + changeMode(newpcbb == idleProcess ? idle : kernel, tc); + + DPRINTF(Context, "Context Switch old pid=%d new pid=%d\n", + Linux::ThreadInfo(tc, oldpcbb).curTaskPID(), + Linux::ThreadInfo(tc, newpcbb).curTaskPID()); +} + +void +Statistics::callpal(int code, ThreadContext *tc) +{ + if (!PAL::name(code)) + return; + + _callpal[code]++; + + switch (code) { + case PAL::callsys: { + int number = tc->readIntReg(0); + if (SystemCalls::validSyscallNumber(number)) { + int cvtnum = SystemCalls::convert(number); + _syscall[cvtnum]++; + } + } break; + } +} + +void +Statistics::serialize(ostream &os) +{ + ::Kernel::Statistics::serialize(os); + int exemode = themode; + SERIALIZE_SCALAR(exemode); + SERIALIZE_SCALAR(idleProcess); + SERIALIZE_SCALAR(lastModeTick); +} + +void +Statistics::unserialize(Checkpoint *cp, const string §ion) +{ + ::Kernel::Statistics::unserialize(cp, section); + int exemode; + UNSERIALIZE_SCALAR(exemode); + UNSERIALIZE_SCALAR(idleProcess); + UNSERIALIZE_SCALAR(lastModeTick); + themode = (cpu_mode)exemode; +} + +} // namespace Kernel +} // namespace AlphaISA diff --git a/simulators/gem5/src/arch/alpha/kernel_stats.hh b/simulators/gem5/src/arch/alpha/kernel_stats.hh new file mode 100644 index 00000000..83726930 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/kernel_stats.hh @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Lisa Hsu + * Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_KERNEL_STATS_HH__ +#define __ARCH_ALPHA_KERNEL_STATS_HH__ + +#include +#include +#include +#include + +#include "cpu/static_inst.hh" +#include "kern/kernel_stats.hh" + +class BaseCPU; +class ThreadContext; +class FnEvent; +// What does kernel stats expect is included? +class System; + +namespace AlphaISA { +namespace Kernel { + +enum cpu_mode { kernel, user, idle, cpu_mode_num }; +extern const char *modestr[]; + +class Statistics : public ::Kernel::Statistics +{ + protected: + Addr idleProcess; + cpu_mode themode; + Tick lastModeTick; + + void changeMode(cpu_mode newmode, ThreadContext *tc); + + private: + Stats::Vector _callpal; +// Stats::Vector _faults; + + Stats::Vector _mode; + Stats::Vector _modeGood; + Stats::Formula _modeFraction; + Stats::Vector _modeTicks; + + Stats::Scalar _swap_context; + + public: + Statistics(System *system); + + void regStats(const std::string &name); + + public: + void mode(cpu_mode newmode, ThreadContext *tc); + void context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc); + void callpal(int code, ThreadContext *tc); + void hwrei() { _hwrei++; } + + void setIdleProcess(Addr idle, ThreadContext *tc); + + public: + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); +}; + +} // namespace Kernel +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_KERNEL_STATS_HH__ diff --git a/simulators/gem5/src/arch/alpha/kgdb.h b/simulators/gem5/src/arch/alpha/kgdb.h new file mode 100644 index 00000000..0883dc02 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/kgdb.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1992, 1993 The Regents of the University of California + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)remote-sl.h 8.1 (Berkeley) 6/11/93 + */ + +/* $NetBSD: kgdb.h,v 1.4 1998/08/13 02:10:59 eeh Exp $ */ + +#ifndef __KGDB_H__ +#define __KGDB_H__ + +/* + * Message types. + */ +#define KGDB_SIGNAL '?' // last sigal +#define KGDB_SET_BAUD 'b' // set baud (deprecated) +#define KGDB_SET_BREAK 'B' // set breakpoint (deprecated) +#define KGDB_CONT 'c' // resume +#define KGDB_ASYNC_CONT 'C' // continue with signal +#define KGDB_DEBUG 'd' // toggle debug flags (deprecated) +#define KGDB_DETACH 'D' // detach remote gdb +#define KGDB_REG_R 'g' // read general registers +#define KGDB_REG_W 'G' // write general registers +#define KGDB_SET_THREAD 'H' // set thread +#define KGDB_CYCLE_STEP 'i' // step a single cycle +#define KGDB_SIG_CYCLE_STEP 'I' // signal then single cycle step +#define KGDB_KILL 'k' // kill program +#define KGDB_MEM_R 'm' // read memory +#define KGDB_MEM_W 'M' // write memory +#define KGDB_READ_REG 'p' // read register +#define KGDB_SET_REG 'P' // write register +#define KGDB_QUERY_VAR 'q' // query variable +#define KGDB_SET_VAR 'Q' // set variable +#define KGDB_RESET 'r' // reset system. (Deprecated) +#define KGDB_STEP 's' // step +#define KGDB_ASYNC_STEP 'S' // signal and step +#define KGDB_THREAD_ALIVE 'T' // find out if the thread is alive. +#define KGDB_TARGET_EXIT 'W' // target exited +#define KGDB_BINARY_DLOAD 'X' // write memory +#define KGDB_CLR_HW_BKPT 'z' // remove breakpoint or watchpoint +#define KGDB_SET_HW_BKPT 'Z' // insert breakpoint or watchpoint + +/* + * start of frame/end of frame + */ +#define KGDB_START '$' +#define KGDB_END '#' +#define KGDB_GOODP '+' +#define KGDB_BADP '-' + +/* + * Stuff for KGDB. + */ +#define KGDB_NUMREGS 66 /* from tm-alpha.h, NUM_REGS */ +#define KGDB_REG_V0 0 +#define KGDB_REG_T0 1 +#define KGDB_REG_T1 2 +#define KGDB_REG_T2 3 +#define KGDB_REG_T3 4 +#define KGDB_REG_T4 5 +#define KGDB_REG_T5 6 +#define KGDB_REG_T6 7 +#define KGDB_REG_T7 8 +#define KGDB_REG_S0 9 +#define KGDB_REG_S1 10 +#define KGDB_REG_S2 11 +#define KGDB_REG_S3 12 +#define KGDB_REG_S4 13 +#define KGDB_REG_S5 14 +#define KGDB_REG_S6 15 /* FP */ +#define KGDB_REG_A0 16 +#define KGDB_REG_A1 17 +#define KGDB_REG_A2 18 +#define KGDB_REG_A3 19 +#define KGDB_REG_A4 20 +#define KGDB_REG_A5 21 +#define KGDB_REG_T8 22 +#define KGDB_REG_T9 23 +#define KGDB_REG_T10 24 +#define KGDB_REG_T11 25 +#define KGDB_REG_RA 26 +#define KGDB_REG_T12 27 +#define KGDB_REG_AT 28 +#define KGDB_REG_GP 29 +#define KGDB_REG_SP 30 +#define KGDB_REG_ZERO 31 +#define KGDB_REG_F0 32 +#define KGDB_REG_F1 33 +#define KGDB_REG_F2 34 +#define KGDB_REG_F3 35 +#define KGDB_REG_F4 36 +#define KGDB_REG_F5 37 +#define KGDB_REG_F6 38 +#define KGDB_REG_F7 39 +#define KGDB_REG_F8 40 +#define KGDB_REG_F9 41 +#define KGDB_REG_F10 42 +#define KGDB_REG_F11 43 +#define KGDB_REG_F12 44 +#define KGDB_REG_F13 45 +#define KGDB_REG_F14 46 +#define KGDB_REG_F15 47 +#define KGDB_REG_F16 48 +#define KGDB_REG_F17 49 +#define KGDB_REG_F18 50 +#define KGDB_REG_F19 51 +#define KGDB_REG_F20 52 +#define KGDB_REG_F21 53 +#define KGDB_REG_F22 54 +#define KGDB_REG_F23 55 +#define KGDB_REG_F24 56 +#define KGDB_REG_F25 57 +#define KGDB_REG_F26 58 +#define KGDB_REG_F27 59 +#define KGDB_REG_F28 60 +#define KGDB_REG_F29 61 +#define KGDB_REG_F30 62 +#define KGDB_REG_F31 63 +#define KGDB_REG_PC 64 +#define KGDB_REG_VFP 65 + +/* Too much? Must be large enough for register transfer. */ +#define KGDB_BUFLEN 1024 + +#endif /* __KGDB_H__ */ diff --git a/simulators/gem5/src/arch/alpha/linux/linux.cc b/simulators/gem5/src/arch/alpha/linux/linux.cc new file mode 100644 index 00000000..ad838809 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/linux.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#include + +#include "arch/alpha/linux/linux.hh" + +// open(2) flags translation table +OpenFlagTransTable AlphaLinux::openFlagTable[] = { +#ifdef _MSC_VER + { AlphaLinux::TGT_O_RDONLY, _O_RDONLY }, + { AlphaLinux::TGT_O_WRONLY, _O_WRONLY }, + { AlphaLinux::TGT_O_RDWR, _O_RDWR }, + { AlphaLinux::TGT_O_APPEND, _O_APPEND }, + { AlphaLinux::TGT_O_CREAT, _O_CREAT }, + { AlphaLinux::TGT_O_TRUNC, _O_TRUNC }, + { AlphaLinux::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { AlphaLinux::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { AlphaLinux::TGT_O_RDONLY, O_RDONLY }, + { AlphaLinux::TGT_O_WRONLY, O_WRONLY }, + { AlphaLinux::TGT_O_RDWR, O_RDWR }, + { AlphaLinux::TGT_O_APPEND, O_APPEND }, + { AlphaLinux::TGT_O_CREAT, O_CREAT }, + { AlphaLinux::TGT_O_TRUNC, O_TRUNC }, + { AlphaLinux::TGT_O_EXCL, O_EXCL }, + { AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { AlphaLinux::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { AlphaLinux::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int AlphaLinux::NUM_OPEN_FLAGS = + (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0])); diff --git a/simulators/gem5/src/arch/alpha/linux/linux.hh b/simulators/gem5/src/arch/alpha/linux/linux.hh new file mode 100644 index 00000000..3304816c --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/linux.hh @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ALPHA_ALPHA_LINUX_LINUX_HH__ +#define __ALPHA_ALPHA_LINUX_LINUX_HH__ + +#include "kern/linux/linux.hh" + +/* AlphaLinux class contains static constants/definitions/misc. + * structures which are specific to the Linux OS AND the Alpha + * architecture + */ +class AlphaLinux : public Linux +{ + public: + + /// This table maps the target open() flags to the corresponding + /// host open() flags. + static OpenFlagTransTable openFlagTable[]; + + /// Number of entries in openFlagTable[]. + static const int NUM_OPEN_FLAGS; + + //@{ + /// open(2) flag values. + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x10; + static const unsigned TGT_MAP_FIXED = 0x100; + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + static const unsigned GSI_IEEE_FP_CONTROL = 45; + //@} + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + static const int TGT_RUSAGE_BOTH = -2; + //@} + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + //@{ + /// ioctl() command codes. + static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCSETP_ = 0x80067409; + static const unsigned TIOCSETN_ = 0x8006740a; + static const unsigned TIOCSETC_ = 0x80067411; + static const unsigned TIOCGETC_ = 0x40067412; + static const unsigned FIONREAD_ = 0x4004667f; + static const unsigned TIOCISATTY_ = 0x2000745e; + static const unsigned TIOCGETS_ = 0x402c7413; + static const unsigned TIOCGETA_ = 0x40127417; + static const unsigned TCSETAW_ = 0x80147419; // 2.6.15 kernel + //@} + + /// For table(). + static const int TBL_SYSINFO = 12; + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NOFILE = 6, + TGT_RLIMIT_AS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; + + typedef struct { + int64_t uptime; /* Seconds since boot */ + uint64_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint64_t totalram; /* Total usable main memory size */ + uint64_t freeram; /* Available memory size */ + uint64_t sharedram; /* Amount of shared memory */ + uint64_t bufferram; /* Memory used by buffers */ + uint64_t totalswap; /* Total swap space size */ + uint64_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint64_t totalhigh; /* Total high memory size */ + uint64_t freehigh; /* Available high memory size */ + uint64_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; +}; + +#endif // __ALPHA_ALPHA_LINUX_LINUX_HH__ diff --git a/simulators/gem5/src/arch/alpha/linux/process.cc b/simulators/gem5/src/arch/alpha/linux/process.cc new file mode 100644 index 00000000..f4457b38 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/process.cc @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Ali Saidi + */ + +#include "arch/alpha/linux/linux.hh" +#include "arch/alpha/linux/process.hh" +#include "arch/alpha/isa_traits.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/SyscallVerbose.hh" +#include "kern/linux/linux.hh" +#include "sim/process.hh" +#include "sim/syscall_emul.hh" + +using namespace std; +using namespace AlphaISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + TypedBufferArg name(process->getSyscallArg(tc, index)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.6.26"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "alpha"); + + name.copyOut(tc->getMemProxy()); + return 0; +} + +/// Target osf_getsysyinfo() handler. Even though this call is +/// borrowed from Tru64, the subcases that get used appear to be +/// different in practice from those used by Tru64 processes. +static SyscallReturn +osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); + // unsigned nbytes = process->getSyscallArg(tc, 2); + + switch (op) { + + case 45: { // GSI_IEEE_FP_CONTROL + TypedBufferArg fpcr(bufPtr); + // I don't think this exactly matches the HW FPCR + *fpcr = 0; + fpcr.copyOut(tc->getMemProxy()); + return 0; + } + + default: + cerr << "osf_getsysinfo: unknown op " << op << endl; + abort(); + break; + } + + return 1; +} + +/// Target osf_setsysinfo() handler. +static SyscallReturn +osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); + // unsigned nbytes = process->getSyscallArg(tc, 2); + + switch (op) { + + case 14: { // SSI_IEEE_FP_CONTROL + TypedBufferArg fpcr(bufPtr); + // I don't think this exactly matches the HW FPCR + fpcr.copyIn(tc->getMemProxy()); + DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " + " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); + return 0; + } + + default: + cerr << "osf_setsysinfo: unknown op " << op << endl; + abort(); + break; + } + + return 1; +} + + +SyscallDesc AlphaLinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("osf_old_open", unimplementedFunc), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("osf_wait4", unimplementedFunc), + /* 8 */ SyscallDesc("osf_old_creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("osf_execve", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("fchdir", unimplementedFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc), + /* 16 */ SyscallDesc("chown", chownFunc), + /* 17 */ SyscallDesc("brk", brkFunc), + /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc), + /* 21 */ SyscallDesc("osf_mount", unimplementedFunc), + /* 22 */ SyscallDesc("umount", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getxuid", getuidPseudoFunc), + /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc), + /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc), + /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc), + /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc), + /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc), + /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc), + /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc), + /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc), + /* 39 */ SyscallDesc("setpgid", unimplementedFunc), + /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", dupFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc), + /* 44 */ SyscallDesc("osf_profil", unimplementedFunc), + /* 45 */ SyscallDesc("open", openFunc), + /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc), + /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc), + /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc), + /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc), + /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("sigpending", unimplementedFunc), + /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", ioctlFunc), + /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc), + /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc), + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", readlinkFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc), + /* 63 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), + /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc), + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("stat", statFunc), + /* 68 */ SyscallDesc("lstat", lstatFunc), + /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc), + /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc), + /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", ignoreFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("osf_kmodcall", unimplementedFunc), + /* 78 */ SyscallDesc("osf_mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), + /* 81 */ SyscallDesc("osf_old_getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setpgrp", unimplementedFunc), + /* 83 */ SyscallDesc("osf_setitimer", unimplementedFunc), + /* 84 */ SyscallDesc("osf_old_wait", unimplementedFunc), + /* 85 */ SyscallDesc("osf_table", unimplementedFunc), + /* 86 */ SyscallDesc("osf_getitimer", unimplementedFunc), + /* 87 */ SyscallDesc("gethostname", gethostnameFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), + /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("fstat", fstatFunc), + /* 92 */ SyscallDesc("fcntl", fcntlFunc), + /* 93 */ SyscallDesc("osf_select", unimplementedFunc), + /* 94 */ SyscallDesc("poll", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), + /* 101 */ SyscallDesc("send", unimplementedFunc), + /* 102 */ SyscallDesc("recv", unimplementedFunc), + /* 103 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 104 */ SyscallDesc("bind", unimplementedFunc), + /* 105 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 106 */ SyscallDesc("listen", unimplementedFunc), + /* 107 */ SyscallDesc("osf_plock", unimplementedFunc), + /* 108 */ SyscallDesc("osf_old_sigvec", unimplementedFunc), + /* 109 */ SyscallDesc("osf_old_sigblock", unimplementedFunc), + /* 110 */ SyscallDesc("osf_old_sigsetmask", unimplementedFunc), + /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 112 */ SyscallDesc("osf_sigstack", ignoreFunc), + /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("osf_old_vtrace", unimplementedFunc), + /* 116 */ SyscallDesc("osf_gettimeofday", unimplementedFunc), + /* 117 */ SyscallDesc("osf_getrusage", unimplementedFunc), + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", writevFunc), + /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", fchownFunc), + /* 124 */ SyscallDesc("fchmod", fchmodFunc), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), + /* 127 */ SyscallDesc("setregid", unimplementedFunc), + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", truncateFunc), + /* 130 */ SyscallDesc("ftruncate", ftruncateFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("setgid", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", mkdirFunc), + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc), + /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc), + /* 140 */ SyscallDesc("osf_adjtime", unimplementedFunc), + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc), + /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", getrlimitFunc), + /* 145 */ SyscallDesc("setrlimit", ignoreFunc), + /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc), + /* 147 */ SyscallDesc("setsid", unimplementedFunc), + /* 148 */ SyscallDesc("quotactl", unimplementedFunc), + /* 149 */ SyscallDesc("osf_oldquota", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("osf_pread", unimplementedFunc), + /* 152 */ SyscallDesc("osf_pwrite", unimplementedFunc), + /* 153 */ SyscallDesc("osf_pid_block", unimplementedFunc), + /* 154 */ SyscallDesc("osf_pid_unblock", unimplementedFunc), + /* 155 */ SyscallDesc("osf_signal_urti", unimplementedFunc), + /* 156 */ SyscallDesc("sigaction", ignoreFunc), + /* 157 */ SyscallDesc("osf_sigwaitprim", unimplementedFunc), + /* 158 */ SyscallDesc("osf_nfssvc", unimplementedFunc), + /* 159 */ SyscallDesc("osf_getdirentries", unimplementedFunc), + /* 160 */ SyscallDesc("osf_statfs", unimplementedFunc), + /* 161 */ SyscallDesc("osf_fstatfs", unimplementedFunc), + /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), + /* 163 */ SyscallDesc("osf_async_daemon", unimplementedFunc), + /* 164 */ SyscallDesc("osf_getfh", unimplementedFunc), + /* 165 */ SyscallDesc("osf_getdomainname", unimplementedFunc), + /* 166 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 167 */ SyscallDesc("unknown #167", unimplementedFunc), + /* 168 */ SyscallDesc("unknown #168", unimplementedFunc), + /* 169 */ SyscallDesc("osf_exportfs", unimplementedFunc), + /* 170 */ SyscallDesc("unknown #170", unimplementedFunc), + /* 171 */ SyscallDesc("unknown #171", unimplementedFunc), + /* 172 */ SyscallDesc("unknown #172", unimplementedFunc), + /* 173 */ SyscallDesc("unknown #173", unimplementedFunc), + /* 174 */ SyscallDesc("unknown #174", unimplementedFunc), + /* 175 */ SyscallDesc("unknown #175", unimplementedFunc), + /* 176 */ SyscallDesc("unknown #176", unimplementedFunc), + /* 177 */ SyscallDesc("unknown #177", unimplementedFunc), + /* 178 */ SyscallDesc("unknown #178", unimplementedFunc), + /* 179 */ SyscallDesc("unknown #179", unimplementedFunc), + /* 180 */ SyscallDesc("unknown #180", unimplementedFunc), + /* 181 */ SyscallDesc("osf_alt_plock", unimplementedFunc), + /* 182 */ SyscallDesc("unknown #182", unimplementedFunc), + /* 183 */ SyscallDesc("unknown #183", unimplementedFunc), + /* 184 */ SyscallDesc("osf_getmnt", unimplementedFunc), + /* 185 */ SyscallDesc("unknown #185", unimplementedFunc), + /* 186 */ SyscallDesc("unknown #186", unimplementedFunc), + /* 187 */ SyscallDesc("osf_alt_sigpending", unimplementedFunc), + /* 188 */ SyscallDesc("osf_alt_setsid", unimplementedFunc), + /* 189 */ SyscallDesc("unknown #189", unimplementedFunc), + /* 190 */ SyscallDesc("unknown #190", unimplementedFunc), + /* 191 */ SyscallDesc("unknown #191", unimplementedFunc), + /* 192 */ SyscallDesc("unknown #192", unimplementedFunc), + /* 193 */ SyscallDesc("unknown #193", unimplementedFunc), + /* 194 */ SyscallDesc("unknown #194", unimplementedFunc), + /* 195 */ SyscallDesc("unknown #195", unimplementedFunc), + /* 196 */ SyscallDesc("unknown #196", unimplementedFunc), + /* 197 */ SyscallDesc("unknown #197", unimplementedFunc), + /* 198 */ SyscallDesc("unknown #198", unimplementedFunc), + /* 199 */ SyscallDesc("osf_swapon", unimplementedFunc), + /* 200 */ SyscallDesc("msgctl", unimplementedFunc), + /* 201 */ SyscallDesc("msgget", unimplementedFunc), + /* 202 */ SyscallDesc("msgrcv", unimplementedFunc), + /* 203 */ SyscallDesc("msgsnd", unimplementedFunc), + /* 204 */ SyscallDesc("semctl", unimplementedFunc), + /* 205 */ SyscallDesc("semget", unimplementedFunc), + /* 206 */ SyscallDesc("semop", unimplementedFunc), + /* 207 */ SyscallDesc("osf_utsname", unimplementedFunc), + /* 208 */ SyscallDesc("lchown", unimplementedFunc), + /* 209 */ SyscallDesc("osf_shmat", unimplementedFunc), + /* 210 */ SyscallDesc("shmctl", unimplementedFunc), + /* 211 */ SyscallDesc("shmdt", unimplementedFunc), + /* 212 */ SyscallDesc("shmget", unimplementedFunc), + /* 213 */ SyscallDesc("osf_mvalid", unimplementedFunc), + /* 214 */ SyscallDesc("osf_getaddressconf", unimplementedFunc), + /* 215 */ SyscallDesc("osf_msleep", unimplementedFunc), + /* 216 */ SyscallDesc("osf_mwakeup", unimplementedFunc), + /* 217 */ SyscallDesc("msync", unimplementedFunc), + /* 218 */ SyscallDesc("osf_signal", unimplementedFunc), + /* 219 */ SyscallDesc("osf_utc_gettime", unimplementedFunc), + /* 220 */ SyscallDesc("osf_utc_adjtime", unimplementedFunc), + /* 221 */ SyscallDesc("unknown #221", unimplementedFunc), + /* 222 */ SyscallDesc("osf_security", unimplementedFunc), + /* 223 */ SyscallDesc("osf_kloadcall", unimplementedFunc), + /* 224 */ SyscallDesc("unknown #224", unimplementedFunc), + /* 225 */ SyscallDesc("unknown #225", unimplementedFunc), + /* 226 */ SyscallDesc("unknown #226", unimplementedFunc), + /* 227 */ SyscallDesc("unknown #227", unimplementedFunc), + /* 228 */ SyscallDesc("unknown #228", unimplementedFunc), + /* 229 */ SyscallDesc("unknown #229", unimplementedFunc), + /* 230 */ SyscallDesc("unknown #230", unimplementedFunc), + /* 231 */ SyscallDesc("unknown #231", unimplementedFunc), + /* 232 */ SyscallDesc("unknown #232", unimplementedFunc), + /* 233 */ SyscallDesc("getpgid", unimplementedFunc), + /* 234 */ SyscallDesc("getsid", unimplementedFunc), + /* 235 */ SyscallDesc("sigaltstack", ignoreFunc), + /* 236 */ SyscallDesc("osf_waitid", unimplementedFunc), + /* 237 */ SyscallDesc("osf_priocntlset", unimplementedFunc), + /* 238 */ SyscallDesc("osf_sigsendset", unimplementedFunc), + /* 239 */ SyscallDesc("osf_set_speculative", unimplementedFunc), + /* 240 */ SyscallDesc("osf_msfs_syscall", unimplementedFunc), + /* 241 */ SyscallDesc("osf_sysinfo", unimplementedFunc), + /* 242 */ SyscallDesc("osf_uadmin", unimplementedFunc), + /* 243 */ SyscallDesc("osf_fuser", unimplementedFunc), + /* 244 */ SyscallDesc("osf_proplist_syscall", unimplementedFunc), + /* 245 */ SyscallDesc("osf_ntp_adjtime", unimplementedFunc), + /* 246 */ SyscallDesc("osf_ntp_gettime", unimplementedFunc), + /* 247 */ SyscallDesc("osf_pathconf", unimplementedFunc), + /* 248 */ SyscallDesc("osf_fpathconf", unimplementedFunc), + /* 249 */ SyscallDesc("unknown #249", unimplementedFunc), + /* 250 */ SyscallDesc("osf_uswitch", unimplementedFunc), + /* 251 */ SyscallDesc("osf_usleep_thread", unimplementedFunc), + /* 252 */ SyscallDesc("osf_audcntl", unimplementedFunc), + /* 253 */ SyscallDesc("osf_audgen", unimplementedFunc), + /* 254 */ SyscallDesc("sysfs", unimplementedFunc), + /* 255 */ SyscallDesc("osf_subsys_info", unimplementedFunc), + /* 256 */ SyscallDesc("osf_getsysinfo", osf_getsysinfoFunc), + /* 257 */ SyscallDesc("osf_setsysinfo", osf_setsysinfoFunc), + /* 258 */ SyscallDesc("osf_afs_syscall", unimplementedFunc), + /* 259 */ SyscallDesc("osf_swapctl", unimplementedFunc), + /* 260 */ SyscallDesc("osf_memcntl", unimplementedFunc), + /* 261 */ SyscallDesc("osf_fdatasync", unimplementedFunc), + /* 262 */ SyscallDesc("unknown #262", unimplementedFunc), + /* 263 */ SyscallDesc("unknown #263", unimplementedFunc), + /* 264 */ SyscallDesc("unknown #264", unimplementedFunc), + /* 265 */ SyscallDesc("unknown #265", unimplementedFunc), + /* 266 */ SyscallDesc("unknown #266", unimplementedFunc), + /* 267 */ SyscallDesc("unknown #267", unimplementedFunc), + /* 268 */ SyscallDesc("unknown #268", unimplementedFunc), + /* 269 */ SyscallDesc("unknown #269", unimplementedFunc), + /* 270 */ SyscallDesc("unknown #270", unimplementedFunc), + /* 271 */ SyscallDesc("unknown #271", unimplementedFunc), + /* 272 */ SyscallDesc("unknown #272", unimplementedFunc), + /* 273 */ SyscallDesc("unknown #273", unimplementedFunc), + /* 274 */ SyscallDesc("unknown #274", unimplementedFunc), + /* 275 */ SyscallDesc("unknown #275", unimplementedFunc), + /* 276 */ SyscallDesc("unknown #276", unimplementedFunc), + /* 277 */ SyscallDesc("unknown #277", unimplementedFunc), + /* 278 */ SyscallDesc("unknown #278", unimplementedFunc), + /* 279 */ SyscallDesc("unknown #279", unimplementedFunc), + /* 280 */ SyscallDesc("unknown #280", unimplementedFunc), + /* 281 */ SyscallDesc("unknown #281", unimplementedFunc), + /* 282 */ SyscallDesc("unknown #282", unimplementedFunc), + /* 283 */ SyscallDesc("unknown #283", unimplementedFunc), + /* 284 */ SyscallDesc("unknown #284", unimplementedFunc), + /* 285 */ SyscallDesc("unknown #285", unimplementedFunc), + /* 286 */ SyscallDesc("unknown #286", unimplementedFunc), + /* 287 */ SyscallDesc("unknown #287", unimplementedFunc), + /* 288 */ SyscallDesc("unknown #288", unimplementedFunc), + /* 289 */ SyscallDesc("unknown #289", unimplementedFunc), + /* 290 */ SyscallDesc("unknown #290", unimplementedFunc), + /* 291 */ SyscallDesc("unknown #291", unimplementedFunc), + /* 292 */ SyscallDesc("unknown #292", unimplementedFunc), + /* 293 */ SyscallDesc("unknown #293", unimplementedFunc), + /* 294 */ SyscallDesc("unknown #294", unimplementedFunc), + /* 295 */ SyscallDesc("unknown #295", unimplementedFunc), + /* 296 */ SyscallDesc("unknown #296", unimplementedFunc), + /* 297 */ SyscallDesc("unknown #297", unimplementedFunc), + /* 298 */ SyscallDesc("unknown #298", unimplementedFunc), + /* 299 */ SyscallDesc("unknown #299", unimplementedFunc), +/* + * Linux-specific system calls begin at 300 + */ + /* 300 */ SyscallDesc("bdflush", unimplementedFunc), + /* 301 */ SyscallDesc("sethae", unimplementedFunc), + /* 302 */ SyscallDesc("mount", unimplementedFunc), + /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc), + /* 304 */ SyscallDesc("swapoff", unimplementedFunc), + /* 305 */ SyscallDesc("getdents", unimplementedFunc), + /* 306 */ SyscallDesc("create_module", unimplementedFunc), + /* 307 */ SyscallDesc("init_module", unimplementedFunc), + /* 308 */ SyscallDesc("delete_module", unimplementedFunc), + /* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 310 */ SyscallDesc("syslog", unimplementedFunc), + /* 311 */ SyscallDesc("reboot", unimplementedFunc), + /* 312 */ SyscallDesc("clone", cloneFunc), + /* 313 */ SyscallDesc("uselib", unimplementedFunc), + /* 314 */ SyscallDesc("mlock", unimplementedFunc), + /* 315 */ SyscallDesc("munlock", unimplementedFunc), + /* 316 */ SyscallDesc("mlockall", unimplementedFunc), + /* 317 */ SyscallDesc("munlockall", unimplementedFunc), + /* 318 */ SyscallDesc("sysinfo", sysinfoFunc), + /* 319 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc), + /* 321 */ SyscallDesc("oldumount", unimplementedFunc), + /* 322 */ SyscallDesc("swapon", unimplementedFunc), + /* 323 */ SyscallDesc("times", ignoreFunc), + /* 324 */ SyscallDesc("personality", unimplementedFunc), + /* 325 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 326 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 327 */ SyscallDesc("ustat", unimplementedFunc), + /* 328 */ SyscallDesc("statfs", unimplementedFunc), + /* 329 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 330 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 331 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 332 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 333 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 334 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 335 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 336 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 337 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 339 */ SyscallDesc("uname", unameFunc), + /* 340 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 341 */ SyscallDesc("mremap", mremapFunc), + /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 343 */ SyscallDesc("setresuid", unimplementedFunc), + /* 344 */ SyscallDesc("getresuid", unimplementedFunc), + /* 345 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 346 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 347 */ SyscallDesc("query_module", unimplementedFunc), + /* 348 */ SyscallDesc("prctl", unimplementedFunc), + /* 349 */ SyscallDesc("pread", unimplementedFunc), + /* 350 */ SyscallDesc("pwrite", unimplementedFunc), + /* 351 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 352 */ SyscallDesc("rt_sigaction", ignoreFunc), + /* 353 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 354 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 355 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 358 */ SyscallDesc("select", unimplementedFunc), + /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc), + /* 360 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 361 */ SyscallDesc("getitimer", unimplementedFunc), + /* 362 */ SyscallDesc("setitimer", unimplementedFunc), + /* 363 */ SyscallDesc("utimes", utimesFunc), + /* 364 */ SyscallDesc("getrusage", getrusageFunc), + /* 365 */ SyscallDesc("wait4", unimplementedFunc), + /* 366 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 367 */ SyscallDesc("getcwd", getcwdFunc), + /* 368 */ SyscallDesc("capget", unimplementedFunc), + /* 369 */ SyscallDesc("capset", unimplementedFunc), + /* 370 */ SyscallDesc("sendfile", unimplementedFunc), + /* 371 */ SyscallDesc("setresgid", unimplementedFunc), + /* 372 */ SyscallDesc("getresgid", unimplementedFunc), + /* 373 */ SyscallDesc("dipc", unimplementedFunc), + /* 374 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 375 */ SyscallDesc("mincore", unimplementedFunc), + /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc), + /* 377 */ SyscallDesc("getdents64", unimplementedFunc), + /* 378 */ SyscallDesc("gettid", unimplementedFunc), + /* 379 */ SyscallDesc("readahead", unimplementedFunc), + /* 380 */ SyscallDesc("security", unimplementedFunc), + /* 381 */ SyscallDesc("tkill", unimplementedFunc), + /* 382 */ SyscallDesc("setxattr", unimplementedFunc), + /* 383 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 384 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 385 */ SyscallDesc("getxattr", unimplementedFunc), + /* 386 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 387 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 388 */ SyscallDesc("listxattr", unimplementedFunc), + /* 389 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 390 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 391 */ SyscallDesc("removexattr", unimplementedFunc), + /* 392 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 393 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 394 */ SyscallDesc("futex", unimplementedFunc), + /* 395 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 396 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 397 */ SyscallDesc("tuxcall", unimplementedFunc), + /* 398 */ SyscallDesc("io_setup", unimplementedFunc), + /* 399 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 400 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 401 */ SyscallDesc("io_submit", unimplementedFunc), + /* 402 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 403 */ SyscallDesc("unknown #403", unimplementedFunc), + /* 404 */ SyscallDesc("unknown #404", unimplementedFunc), + /* 405 */ SyscallDesc("exit_group", exitGroupFunc), // exit all threads... + /* 406 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 407 */ SyscallDesc("sys_epoll_create", unimplementedFunc), + /* 408 */ SyscallDesc("sys_epoll_ctl", unimplementedFunc), + /* 409 */ SyscallDesc("sys_epoll_wait", unimplementedFunc), + /* 410 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 411 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 412 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 413 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 414 */ SyscallDesc("timer_create", unimplementedFunc), + /* 415 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 416 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 417 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 418 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 419 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 420 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 421 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 422 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 423 */ SyscallDesc("semtimedop", unimplementedFunc), + /* 424 */ SyscallDesc("tgkill", unimplementedFunc), + /* 425 */ SyscallDesc("stat64", stat64Func), + /* 426 */ SyscallDesc("lstat64", lstat64Func), + /* 427 */ SyscallDesc("fstat64", fstat64Func), + /* 428 */ SyscallDesc("vserver", unimplementedFunc), + /* 429 */ SyscallDesc("mbind", unimplementedFunc), + /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 432 */ SyscallDesc("mq_open", unimplementedFunc), + /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 436 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 438 */ SyscallDesc("waitid", unimplementedFunc), + /* 439 */ SyscallDesc("add_key", unimplementedFunc), + /* 440 */ SyscallDesc("request_key", unimplementedFunc), + /* 441 */ SyscallDesc("keyctl", unimplementedFunc) +}; + +AlphaLinuxProcess::AlphaLinuxProcess(LiveProcessParams * params, + ObjectFile *objFile) + : AlphaLiveProcess(params, objFile), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +{ + //init_regs->intRegFile[0] = 0; +} + + + +SyscallDesc* +AlphaLinuxProcess::getDesc(int callnum) +{ + if (callnum < 0 || callnum >= Num_Syscall_Descs) + return NULL; + return &syscallDescs[callnum]; +} diff --git a/simulators/gem5/src/arch/alpha/linux/process.hh b/simulators/gem5/src/arch/alpha/linux/process.hh new file mode 100644 index 00000000..9ab7b050 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/process.hh @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + */ + +#ifndef __ALPHA_LINUX_PROCESS_HH__ +#define __ALPHA_LINUX_PROCESS_HH__ + +#include "arch/alpha/process.hh" + +namespace AlphaISA { + +/// A process with emulated Alpha/Linux syscalls. +class AlphaLinuxProcess : public AlphaLiveProcess +{ + public: + /// Constructor. + AlphaLinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + + virtual SyscallDesc* getDesc(int callnum); + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + const int Num_Syscall_Descs; +}; + +} // namespace AlphaISA + +#endif // __ALPHA_LINUX_PROCESS_HH__ diff --git a/simulators/gem5/src/arch/alpha/linux/system.cc b/simulators/gem5/src/arch/alpha/linux/system.cc new file mode 100644 index 00000000..db3c16d7 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/system.cc @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Lisa Hsu + * Nathan Binkert + * Steve Reinhardt + */ + +/** + * @file + * This code loads the linux kernel, console, pal and patches certain + * functions. The symbol tables are loaded so that traces can show + * the executing function and we can skip functions. Various delay + * loops are skipped and their final values manually computed to speed + * up boot time. + */ + +#include "arch/alpha/linux/system.hh" +#include "arch/alpha/linux/threadinfo.hh" +#include "arch/alpha/idle_event.hh" +#include "arch/alpha/system.hh" +#include "arch/vtophys.hh" +#include "base/loader/symtab.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "debug/Thread.hh" +#include "kern/linux/events.hh" +#include "kern/linux/printk.hh" +#include "mem/physical.hh" +#include "mem/port.hh" +#include "sim/arguments.hh" +#include "sim/byteswap.hh" + +using namespace std; +using namespace AlphaISA; +using namespace Linux; + +LinuxAlphaSystem::LinuxAlphaSystem(Params *p) + : AlphaSystem(p) +{ +} + +void +LinuxAlphaSystem::initState() +{ + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + + // Call the initialisation of the super class + AlphaSystem::initState(); + + Addr addr = 0; + + /** + * The symbol swapper_pg_dir marks the beginning of the kernel and + * the location of bootloader passed arguments + */ + if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) { + panic("Could not determine start location of kernel"); + } + + /** + * Since we aren't using a bootloader, we have to copy the + * kernel arguments directly into the kernel's memory. + */ + virtProxy.writeBlob(CommandLine(), + (uint8_t*)params()->boot_osflags.c_str(), + params()->boot_osflags.length()+1); + + /** + * find the address of the est_cycle_freq variable and insert it + * so we don't through the lengthly process of trying to + * calculated it by using the PIT, RTC, etc. + */ + if (kernelSymtab->findAddress("est_cycle_freq", addr)) + virtProxy.write(addr, (uint64_t)(SimClock::Frequency / + params()->boot_cpu_frequency)); + + + /** + * EV5 only supports 127 ASNs so we are going to tell the kernel that the + * paritiuclar EV6 we have only supports 127 asns. + * @todo At some point we should change ev5.hh and the palcode to support + * 255 ASNs. + */ + if (kernelSymtab->findAddress("dp264_mv", addr)) + virtProxy.write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127)); + else + panic("could not find dp264_mv\n"); + +} + +void +LinuxAlphaSystem::setupFuncEvents() +{ + AlphaSystem::setupFuncEvents(); +#ifndef NDEBUG + kernelPanicEvent = addKernelFuncEvent("panic"); + if (!kernelPanicEvent) + panic("could not find kernel symbol \'panic\'"); + +#if 0 + kernelDieEvent = addKernelFuncEvent("die_if_kernel"); + if (!kernelDieEvent) + panic("could not find kernel symbol \'die_if_kernel\'"); +#endif + +#endif + + /** + * Any time ide_delay_50ms, calibarte_delay or + * determine_cpu_caches is called just skip the + * function. Currently determine_cpu_caches only is used put + * information in proc, however if that changes in the future we + * will have to fill in the cache size variables appropriately. + */ + + skipIdeDelay50msEvent = + addKernelFuncEvent("ide_delay_50ms"); + skipDelayLoopEvent = + addKernelFuncEvent("calibrate_delay"); + skipCacheProbeEvent = + addKernelFuncEvent("determine_cpu_caches"); + debugPrintkEvent = addKernelFuncEvent("dprintk"); + idleStartEvent = addKernelFuncEvent("cpu_idle"); + + // Disable for now as it runs into panic() calls in VPTr methods + // (see sim/vptr.hh). Once those bugs are fixed, we can + // re-enable, but we should find a better way to turn it on than + // using DTRACE(Thread), since looking at a trace flag at tick 0 + // leads to non-intuitive behavior with --trace-start. + Addr addr = 0; + if (false && kernelSymtab->findAddress("alpha_switch_to", addr)) { + printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo", + addr + sizeof(MachInst) * 6); + } else { + printThreadEvent = NULL; + } +} + +LinuxAlphaSystem::~LinuxAlphaSystem() +{ +#ifndef NDEBUG + delete kernelPanicEvent; +#endif + delete skipIdeDelay50msEvent; + delete skipDelayLoopEvent; + delete skipCacheProbeEvent; + delete debugPrintkEvent; + delete idleStartEvent; + delete printThreadEvent; +} + +void +LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) +{ + Addr addr = 0; + if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { + Tick cpuFreq = tc->getCpuPtr()->frequency(); + assert(intrFreq); + FSTranslatingPortProxy &vp = tc->getVirtProxy(); + vp.writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988)); + } +} + +void +LinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc) +{ + SkipFuncEvent::process(tc); + // calculate and set loops_per_jiffy + ((LinuxAlphaSystem *)tc->getSystemPtr())->setDelayLoop(tc); +} + +void +LinuxAlphaSystem::PrintThreadInfo::process(ThreadContext *tc) +{ + Linux::ThreadInfo ti(tc); + + DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n", + ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart()); +} + +LinuxAlphaSystem * +LinuxAlphaSystemParams::create() +{ + return new LinuxAlphaSystem(this); +} diff --git a/simulators/gem5/src/arch/alpha/linux/system.hh b/simulators/gem5/src/arch/alpha/linux/system.hh new file mode 100644 index 00000000..345c17bb --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/system.hh @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Lisa Hsu + * Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_LINUX_SYSTEM_HH__ +#define __ARCH_ALPHA_LINUX_SYSTEM_HH__ + +class ThreadContext; + +class BreakPCEvent; +class IdleStartEvent; + +#include "arch/alpha/idle_event.hh" +#include "arch/alpha/system.hh" +#include "kern/linux/events.hh" +#include "params/LinuxAlphaSystem.hh" + +/** + * This class contains linux specific system code (Loading, Events). + * It points to objects that are the system binaries to load and patches them + * appropriately to work in simulator. + */ +class LinuxAlphaSystem : public AlphaSystem +{ + private: + struct SkipDelayLoopEvent : public SkipFuncEvent + { + SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr) + : SkipFuncEvent(q, desc, addr) {} + virtual void process(ThreadContext *tc); + }; + + struct PrintThreadInfo : public PCEvent + { + PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr) + : PCEvent(q, desc, addr) {} + virtual void process(ThreadContext *tc); + }; + + /** + * Addresses defining where the kernel bootloader places various + * elements. Details found in include/asm-alpha/system.h + */ + Addr KernelStart; // Lookup the symbol swapper_pg_dir + + public: + Addr InitStack() const { return KernelStart + 0x02000; } + Addr EmptyPGT() const { return KernelStart + 0x04000; } + Addr EmptyPGE() const { return KernelStart + 0x08000; } + Addr ZeroPGE() const { return KernelStart + 0x0A000; } + Addr StartAddr() const { return KernelStart + 0x10000; } + + Addr Param() const { return ZeroPGE() + 0x0; } + Addr CommandLine() const { return Param() + 0x0; } + Addr InitrdStart() const { return Param() + 0x100; } + Addr InitrdSize() const { return Param() + 0x108; } + static const int CommandLineSize = 256; + + private: +#ifndef NDEBUG + /** Event to halt the simulator if the kernel calls panic() */ + BreakPCEvent *kernelPanicEvent; + + /** Event to halt the simulator if the kernel calls die_if_kernel */ + BreakPCEvent *kernelDieEvent; +#endif + + /** + * Event to skip determine_cpu_caches() because we don't support + * the IPRs that the code can access to figure out cache sizes + */ + SkipFuncEvent *skipCacheProbeEvent; + + /** PC based event to skip the ide_delay_50ms() call */ + SkipFuncEvent *skipIdeDelay50msEvent; + + /** + * PC based event to skip the dprink() call and emulate its + * functionality + */ + Linux::DebugPrintkEvent *debugPrintkEvent; + + /** + * Skip calculate_delay_loop() rather than waiting for this to be + * calculated + */ + SkipDelayLoopEvent *skipDelayLoopEvent; + + /** + * Event to print information about thread switches if the trace flag + * Thread is set + */ + PrintThreadInfo *printThreadEvent; + + /** Grab the PCBB of the idle process when it starts */ + IdleStartEvent *idleStartEvent; + + protected: + /** Setup all the function events. Must be done after init() for Alpha since + * fixFuncEvent() requires a function port + */ + virtual void setupFuncEvents(); + + public: + typedef LinuxAlphaSystemParams Params; + LinuxAlphaSystem(Params *p); + ~LinuxAlphaSystem(); + + /** + * Initialise the system + */ + virtual void initState(); + + void setDelayLoop(ThreadContext *tc); + + const Params *params() const { return (const Params *)_params; } +}; + +#endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__ diff --git a/simulators/gem5/src/arch/alpha/linux/threadinfo.hh b/simulators/gem5/src/arch/alpha/linux/threadinfo.hh new file mode 100644 index 00000000..94e362fe --- /dev/null +++ b/simulators/gem5/src/arch/alpha/linux/threadinfo.hh @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_LINUX_LINUX_TREADNIFO_HH__ +#define __ARCH_ALPHA_LINUX_LINUX_TREADNIFO_HH__ + +#include "cpu/thread_context.hh" +#include "sim/system.hh" +#include "sim/vptr.hh" + +namespace Linux { + +class ThreadInfo +{ + private: + ThreadContext *tc; + System *sys; + Addr pcbb; + + template + bool + get_data(const char *symbol, T &data) + { + Addr addr = 0; + if (!sys->kernelSymtab->findAddress(symbol, addr)) + return false; + + CopyOut(tc, &data, addr, sizeof(T)); + + data = AlphaISA::gtoh(data); + + return true; + } + + public: + ThreadInfo(ThreadContext *_tc, Addr _pcbb = 0) + : tc(_tc), sys(tc->getSystemPtr()), pcbb(_pcbb) + { + + } + ~ThreadInfo() + {} + + inline Addr + curThreadInfo() + { + Addr addr = pcbb; + Addr sp; + + if (!addr) + addr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23); + + PortProxy &p = tc->getPhysProxy(); + p.readBlob(addr, (uint8_t *)&sp, sizeof(Addr)); + + return sp & ~ULL(0x3fff); + } + + inline Addr + curTaskInfo(Addr thread_info = 0) + { + int32_t offset; + if (!get_data("thread_info_task", offset)) + return 0; + + if (!thread_info) + thread_info = curThreadInfo(); + + Addr addr; + CopyOut(tc, &addr, thread_info + offset, sizeof(addr)); + + return addr; + } + + int32_t + curTaskPID(Addr thread_info = 0) + { + int32_t offset; + if (!get_data("task_struct_pid", offset)) + return -1; + + int32_t pid; + CopyOut(tc, &pid, curTaskInfo(thread_info) + offset, sizeof(pid)); + + return pid; + } + + int64_t + curTaskStart(Addr thread_info = 0) + { + int32_t offset; + if (!get_data("task_struct_start_time", offset)) + return -1; + + int64_t data; + // start_time is actually of type timespec, but if we just + // grab the first long, we'll get the seconds out of it + CopyOut(tc, &data, curTaskInfo(thread_info) + offset, sizeof(data)); + + return data; + } + + std::string + curTaskName(Addr thread_info = 0) + { + int32_t offset; + int32_t size; + + if (!get_data("task_struct_comm", offset)) + return "FailureIn_curTaskName"; + + if (!get_data("task_struct_comm_size", size)) + return "FailureIn_curTaskName"; + + char buffer[size + 1]; + CopyStringOut(tc, buffer, curTaskInfo(thread_info) + offset, size); + + return buffer; + } +}; + +} // namespace Linux + +#endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__ diff --git a/simulators/gem5/src/arch/alpha/locked_mem.hh b/simulators/gem5/src/arch/alpha/locked_mem.hh new file mode 100644 index 00000000..24d028b5 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/locked_mem.hh @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_LOCKED_MEM_HH__ +#define __ARCH_ALPHA_LOCKED_MEM_HH__ + +/** + * @file + * + * ISA-specific helper functions for locked memory accesses. + * + * Note that these functions are not embedded in the ISA description + * because they operate on the *physical* address rather than the + * virtual address. In the current M5 design, the physical address is + * not accessible from the ISA description, only from the CPU model. + * Thus the CPU is responsible for calling back to the ISA (here) + * after the address translation has been performed to allow the ISA + * to do these manipulations based on the physical address. + */ + +#include "arch/alpha/registers.hh" +#include "base/misc.hh" +#include "mem/request.hh" + +namespace AlphaISA { + +template +inline void +handleLockedRead(XC *xc, Request *req) +{ + xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr() & ~0xf); + xc->setMiscReg(MISCREG_LOCKFLAG, true); +} + + +template +inline bool +handleLockedWrite(XC *xc, Request *req) +{ + if (req->isUncacheable()) { + // Funky Turbolaser mailbox access...don't update + // result register (see stq_c in decoder.isa) + req->setExtraData(2); + } else { + // standard store conditional + bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG); + Addr lock_addr = xc->readMiscReg(MISCREG_LOCKADDR); + if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) { + // Lock flag not set or addr mismatch in CPU; + // don't even bother sending to memory system + req->setExtraData(0); + xc->setMiscReg(MISCREG_LOCKFLAG, false); + // the rest of this code is not architectural; + // it's just a debugging aid to help detect + // livelock by warning on long sequences of failed + // store conditionals + int stCondFailures = xc->readStCondFailures(); + stCondFailures++; + xc->setStCondFailures(stCondFailures); + if (stCondFailures % 100000 == 0) { + warn("context %d: %d consecutive " + "store conditional failures\n", + xc->contextId(), stCondFailures); + } + + // store conditional failed already, so don't issue it to mem + return false; + } + } + + return true; +} + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_LOCKED_MEM_HH__ diff --git a/simulators/gem5/src/arch/alpha/microcode_rom.hh b/simulators/gem5/src/arch/alpha/microcode_rom.hh new file mode 100644 index 00000000..ef060258 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/microcode_rom.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ALPHA_MICROCODE_ROM_HH__ +#define __ARCH_ALPHA_MICROCODE_ROM_HH__ + +#include "sim/microcode_rom.hh" + +namespace AlphaISA +{ + using ::MicrocodeRom; +} + +#endif // __ARCH_ALPHA_MICROCODE_ROM_HH__ diff --git a/simulators/gem5/src/arch/alpha/mmapped_ipr.hh b/simulators/gem5/src/arch/alpha/mmapped_ipr.hh new file mode 100644 index 00000000..6c3403b3 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/mmapped_ipr.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#ifndef __ARCH_ALPHA_MMAPPED_IPR_HH__ +#define __ARCH_ALPHA_MMAPPED_IPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "base/types.hh" +#include "mem/packet.hh" + +class ThreadContext; + +namespace AlphaISA { + +inline Tick +handleIprRead(ThreadContext *xc, Packet *pkt) +{ + panic("No handleIprRead implementation in Alpha\n"); +} + + +inline Tick +handleIprWrite(ThreadContext *xc, Packet *pkt) +{ + panic("No handleIprWrite implementation in Alpha\n"); +} + + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_MMAPPED_IPR_HH__ diff --git a/simulators/gem5/src/arch/alpha/mt.hh b/simulators/gem5/src/arch/alpha/mt.hh new file mode 100644 index 00000000..cce27303 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/mt.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __ARCH_ALPHA_MT_HH__ +#define __ARCH_ALPHA_MT_HH__ + +/** + * @file + * + * ISA-specific helper functions for multithreaded execution. + */ + +#include + +#include "arch/isa_traits.hh" +#include "base/bitfield.hh" +#include "base/misc.hh" +#include "base/trace.hh" + +namespace AlphaISA +{ + +template +inline unsigned +getVirtProcNum(TC *tc) +{ + fatal("Alpha is not setup for multithreaded ISA extensions"); + return 0; +} + + +template +inline unsigned +getTargetThread(TC *tc) +{ + fatal("Alpha is not setup for multithreaded ISA extensions"); + return 0; +} + +} // namespace AlphaISA + +#endif diff --git a/simulators/gem5/src/arch/alpha/osfpal.cc b/simulators/gem5/src/arch/alpha/osfpal.cc new file mode 100644 index 00000000..58a3d31e --- /dev/null +++ b/simulators/gem5/src/arch/alpha/osfpal.cc @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include "arch/alpha/osfpal.hh" + +const char * +PAL::name(int index) +{ + static const char *strings[PAL::NumCodes] = { + // Priviledged PAL instructions + "halt", // 0x00 + "cflush", // 0x01 + "draina", // 0x02 + 0, // 0x03 + 0, // 0x04 + 0, // 0x05 + 0, // 0x06 + 0, // 0x07 + 0, // 0x08 + "cserve", // 0x09 + "swppal", // 0x0a + 0, // 0x0b + 0, // 0x0c + "wripir", // 0x0d + 0, // 0x0e + 0, // 0x0f + "rdmces", // 0x10 + "wrmces", // 0x11 + 0, // 0x12 + 0, // 0x13 + 0, // 0x14 + 0, // 0x15 + 0, // 0x16 + 0, // 0x17 + 0, // 0x18 + 0, // 0x19 + 0, // 0x1a + 0, // 0x1b + 0, // 0x1c + 0, // 0x1d + 0, // 0x1e + 0, // 0x1f + 0, // 0x20 + 0, // 0x21 + 0, // 0x22 + 0, // 0x23 + 0, // 0x24 + 0, // 0x25 + 0, // 0x26 + 0, // 0x27 + 0, // 0x28 + 0, // 0x29 + 0, // 0x2a + "wrfen", // 0x2b + 0, // 0x2c + "wrvptptr", // 0x2d + 0, // 0x2e + 0, // 0x2f + "swpctx", // 0x30 + "wrval", // 0x31 + "rdval", // 0x32 + "tbi", // 0x33 + "wrent", // 0x34 + "swpipl", // 0x35 + "rdps", // 0x36 + "wrkgp", // 0x37 + "wrusp", // 0x38 + "wrperfmon", // 0x39 + "rdusp", // 0x3a + 0, // 0x3b + "whami", // 0x3c + "retsys", // 0x3d + "wtint", // 0x3e + "rti", // 0x3f + 0, // 0x40 + 0, // 0x41 + 0, // 0x42 + 0, // 0x43 + 0, // 0x44 + 0, // 0x45 + 0, // 0x46 + 0, // 0x47 + 0, // 0x48 + 0, // 0x49 + 0, // 0x4a + 0, // 0x4b + 0, // 0x4c + 0, // 0x4d + 0, // 0x4e + 0, // 0x4f + 0, // 0x50 + 0, // 0x51 + 0, // 0x52 + 0, // 0x53 + 0, // 0x54 + 0, // 0x55 + 0, // 0x56 + 0, // 0x57 + 0, // 0x58 + 0, // 0x59 + 0, // 0x5a + 0, // 0x5b + 0, // 0x5c + 0, // 0x5d + 0, // 0x5e + 0, // 0x5f + 0, // 0x60 + 0, // 0x61 + 0, // 0x62 + 0, // 0x63 + 0, // 0x64 + 0, // 0x65 + 0, // 0x66 + 0, // 0x67 + 0, // 0x68 + 0, // 0x69 + 0, // 0x6a + 0, // 0x6b + 0, // 0x6c + 0, // 0x6d + 0, // 0x6e + 0, // 0x6f + 0, // 0x70 + 0, // 0x71 + 0, // 0x72 + 0, // 0x73 + 0, // 0x74 + 0, // 0x75 + 0, // 0x76 + 0, // 0x77 + 0, // 0x78 + 0, // 0x79 + 0, // 0x7a + 0, // 0x7b + 0, // 0x7c + 0, // 0x7d + 0, // 0x7e + 0, // 0x7f + + // Unpriviledged PAL instructions + "bpt", // 0x80 + "bugchk", // 0x81 + 0, // 0x82 + "callsys", // 0x83 + 0, // 0x84 + 0, // 0x85 + "imb", // 0x86 + 0, // 0x87 + 0, // 0x88 + 0, // 0x89 + 0, // 0x8a + 0, // 0x8b + 0, // 0x8c + 0, // 0x8d + 0, // 0x8e + 0, // 0x8f + 0, // 0x90 + 0, // 0x91 + "urti", // 0x92 + 0, // 0x93 + 0, // 0x94 + 0, // 0x95 + 0, // 0x96 + 0, // 0x97 + 0, // 0x98 + 0, // 0x99 + 0, // 0x9a + 0, // 0x9b + 0, // 0x9c + 0, // 0x9d + "rdunique", // 0x9e + "wrunique", // 0x9f + 0, // 0xa0 + 0, // 0xa1 + 0, // 0xa2 + 0, // 0xa3 + 0, // 0xa4 + 0, // 0xa5 + 0, // 0xa6 + 0, // 0xa7 + 0, // 0xa8 + 0, // 0xa9 + "gentrap", // 0xaa + 0, // 0xab + 0, // 0xac + 0, // 0xad + "clrfen", // 0xae + 0, // 0xaf + 0, // 0xb0 + 0, // 0xb1 + 0, // 0xb2 + 0, // 0xb3 + 0, // 0xb4 + 0, // 0xb5 + 0, // 0xb6 + 0, // 0xb7 + 0, // 0xb8 + 0, // 0xb9 + 0, // 0xba + 0, // 0xbb + 0, // 0xbc + 0, // 0xbd + "nphalt", // 0xbe + "copypal", // 0xbf +#if 0 + 0, // 0xc0 + 0, // 0xc1 + 0, // 0xc2 + 0, // 0xc3 + 0, // 0xc4 + 0, // 0xc5 + 0, // 0xc6 + 0, // 0xc7 + 0, // 0xc8 + 0, // 0xc9 + 0, // 0xca + 0, // 0xcb + 0, // 0xcc + 0, // 0xcd + 0, // 0xce + 0, // 0xcf + 0, // 0xd0 + 0, // 0xd1 + 0, // 0xd2 + 0, // 0xd3 + 0, // 0xd4 + 0, // 0xd5 + 0, // 0xd6 + 0, // 0xd7 + 0, // 0xd8 + 0, // 0xd9 + 0, // 0xda + 0, // 0xdb + 0, // 0xdc + 0, // 0xdd + 0, // 0xde + 0, // 0xdf + 0, // 0xe0 + 0, // 0xe1 + 0, // 0xe2 + 0, // 0xe3 + 0, // 0xe4 + 0, // 0xe5 + 0, // 0xe6 + 0, // 0xe7 + 0, // 0xe8 + 0, // 0xe9 + 0, // 0xea + 0, // 0xeb + 0, // 0xec + 0, // 0xed + 0, // 0xee + 0, // 0xef + 0, // 0xf0 + 0, // 0xf1 + 0, // 0xf2 + 0, // 0xf3 + 0, // 0xf4 + 0, // 0xf5 + 0, // 0xf6 + 0, // 0xf7 + 0, // 0xf8 + 0, // 0xf9 + 0, // 0xfa + 0, // 0xfb + 0, // 0xfc + 0, // 0xfd + 0, // 0xfe + 0 // 0xff +#endif + }; + + if (index > NumCodes || index < 0) + return 0; + + return strings[index]; +} diff --git a/simulators/gem5/src/arch/alpha/osfpal.hh b/simulators/gem5/src/arch/alpha/osfpal.hh new file mode 100644 index 00000000..2618e9db --- /dev/null +++ b/simulators/gem5/src/arch/alpha/osfpal.hh @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_OSFPAL_HH__ +#define __ARCH_ALPHA_OSFPAL_HH__ + +struct PAL +{ + enum { + // Privileged PAL functions + halt = 0x00, + cflush = 0x01, + draina = 0x02, + cserve = 0x09, + swppal = 0x0a, + wripir = 0x0d, + rdmces = 0x10, + wrmces = 0x11, + wrfen = 0x2b, + wrvptptr = 0x2d, + swpctx = 0x30, + wrval = 0x31, + rdval = 0x32, + tbi = 0x33, + wrent = 0x34, + swpipl = 0x35, + rdps = 0x36, + wrkgp = 0x37, + wrusp = 0x38, + wrperfmon = 0x39, + rdusp = 0x3a, + whami = 0x3c, + retsys = 0x3d, + wtint = 0x3e, + rti = 0x3f, + + // unprivileged pal functions + bpt = 0x80, + bugchk = 0x81, + callsys = 0x83, + imb = 0x86, + urti = 0x92, + rdunique = 0x9e, + wrunique = 0x9f, + gentrap = 0xaa, + clrfen = 0xae, + nphalt = 0xbe, + copypal = 0xbf, + NumCodes + }; + + static const char *name(int index); +}; + +#endif // __ARCH_ALPHA_OSFPAL_HH__ diff --git a/simulators/gem5/src/arch/alpha/pagetable.cc b/simulators/gem5/src/arch/alpha/pagetable.cc new file mode 100644 index 00000000..4dff0477 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/pagetable.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/alpha/pagetable.hh" +#include "sim/serialize.hh" + +namespace AlphaISA { + +void +TlbEntry::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(tag); + SERIALIZE_SCALAR(ppn); + SERIALIZE_SCALAR(xre); + SERIALIZE_SCALAR(xwe); + SERIALIZE_SCALAR(asn); + SERIALIZE_SCALAR(asma); + SERIALIZE_SCALAR(fonr); + SERIALIZE_SCALAR(fonw); + SERIALIZE_SCALAR(valid); +} + +void +TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(tag); + UNSERIALIZE_SCALAR(ppn); + UNSERIALIZE_SCALAR(xre); + UNSERIALIZE_SCALAR(xwe); + UNSERIALIZE_SCALAR(asn); + UNSERIALIZE_SCALAR(asma); + UNSERIALIZE_SCALAR(fonr); + UNSERIALIZE_SCALAR(fonw); + UNSERIALIZE_SCALAR(valid); +} + +} // namespace AlphaISA diff --git a/simulators/gem5/src/arch/alpha/pagetable.hh b/simulators/gem5/src/arch/alpha/pagetable.hh new file mode 100644 index 00000000..b9091d5b --- /dev/null +++ b/simulators/gem5/src/arch/alpha/pagetable.hh @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_PAGETABLE_H__ +#define __ARCH_ALPHA_PAGETABLE_H__ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/utility.hh" + +namespace AlphaISA { + +struct VAddr +{ + static const int ImplBits = 43; + static const Addr ImplMask = (ULL(1) << ImplBits) - 1; + static const Addr UnImplMask = ~ImplMask; + + Addr addr; + + VAddr(Addr a) : addr(a) {} + operator Addr() const { return addr; } + const VAddr &operator=(Addr a) { addr = a; return *this; } + + Addr vpn() const { return (addr & ImplMask) >> PageShift; } + Addr page() const { return addr & PageMask; } + Addr offset() const { return addr & PageOffset; } + + Addr level3() const + { return PteAddr(addr >> PageShift); } + Addr level2() const + { return PteAddr(addr >> (NPtePageShift + PageShift)); } + Addr level1() const + { return PteAddr(addr >> (2 * NPtePageShift + PageShift)); } +}; + +struct PageTableEntry +{ + PageTableEntry(uint64_t e) : entry(e) {} + uint64_t entry; + operator uint64_t() const { return entry; } + const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; } + const PageTableEntry &operator=(const PageTableEntry &e) + { entry = e.entry; return *this; } + + Addr _pfn() const { return (entry >> 32) & 0xffffffff; } + Addr _sw() const { return (entry >> 16) & 0xffff; } + int _rsv0() const { return (entry >> 14) & 0x3; } + bool _uwe() const { return (entry >> 13) & 0x1; } + bool _kwe() const { return (entry >> 12) & 0x1; } + int _rsv1() const { return (entry >> 10) & 0x3; } + bool _ure() const { return (entry >> 9) & 0x1; } + bool _kre() const { return (entry >> 8) & 0x1; } + bool _nomb() const { return (entry >> 7) & 0x1; } + int _gh() const { return (entry >> 5) & 0x3; } + bool _asm_() const { return (entry >> 4) & 0x1; } + bool _foe() const { return (entry >> 3) & 0x1; } + bool _fow() const { return (entry >> 2) & 0x1; } + bool _for() const { return (entry >> 1) & 0x1; } + bool valid() const { return (entry >> 0) & 0x1; } + + Addr paddr() const { return _pfn() << PageShift; } +}; + +// ITB/DTB table entry +struct TlbEntry +{ + Addr tag; // virtual page number tag + Addr ppn; // physical page number + uint8_t xre; // read permissions - VMEM_PERM_* mask + uint8_t xwe; // write permissions - VMEM_PERM_* mask + uint8_t asn; // address space number + bool asma; // address space match + bool fonr; // fault on read + bool fonw; // fault on write + bool valid; // valid page table entry + + + //Construct an entry that maps to physical address addr. + TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr) + { + VAddr vaddr(_vaddr); + VAddr paddr(_paddr); + tag = vaddr.vpn(); + ppn = paddr.vpn(); + xre = 15; + xwe = 15; + asn = _asn; + asma = false; + fonr = false; + fonw = false; + valid = true; + } + + TlbEntry() + {} + + void + updateVaddr(Addr new_vaddr) + { + VAddr vaddr(new_vaddr); + tag = vaddr.vpn(); + } + + Addr + pageStart() + { + return ppn << PageShift; + } + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_PAGETABLE_H__ + diff --git a/simulators/gem5/src/arch/alpha/process.cc b/simulators/gem5/src/arch/alpha/process.cc new file mode 100644 index 00000000..07208fb2 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/process.cc @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/process.hh" +#include "base/loader/elf_object.hh" +#include "base/loader/object_file.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "debug/Loader.hh" +#include "mem/page_table.hh" +#include "sim/byteswap.hh" +#include "sim/process_impl.hh" +#include "sim/system.hh" + +using namespace AlphaISA; +using namespace std; + +AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params, + ObjectFile *objFile) + : LiveProcess(params, objFile) +{ + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up stack. On Alpha, stack goes below text section. This + // code should get moved to some architecture-specific spot. + stack_base = objFile->textBase() - (409600+4096); + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0x10000; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + +} + +void +AlphaLiveProcess::argsInit(int intSize, int pageSize) +{ + objFile->loadSections(initVirtMem); + + typedef AuxVector auxv_t; + std::vector auxv; + + ElfObject * elfObject = dynamic_cast(objFile); + if(elfObject) + { + // modern glibc uses a bunch of auxiliary vectors to set up + // TLS as well as do a bunch of other stuff + // these vectors go on the bottom of the stack, below argc/argv/envp + // pointers but above actual arg strings + // I don't have all the ones glibc looks at here, but so far it doesn't + // seem to be a problem. + // check out _dl_aux_init() in glibc/elf/dl-support.c for details + // --Lisa + auxv.push_back(auxv_t(M5_AT_PAGESZ, AlphaISA::VMPageSize)); + auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); + auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); + DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable()); + auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); + auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); + auxv.push_back(auxv_t(M5_AT_UID, uid())); + auxv.push_back(auxv_t(M5_AT_EUID, euid())); + auxv.push_back(auxv_t(M5_AT_GID, gid())); + auxv.push_back(auxv_t(M5_AT_EGID, egid())); + + } + + // Calculate how much space we need for arg & env & auxv arrays. + int argv_array_size = intSize * (argv.size() + 1); + int envp_array_size = intSize * (envp.size() + 1); + int auxv_array_size = intSize * 2 * (auxv.size() + 1); + + int arg_data_size = 0; + for (vector::size_type i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + int env_data_size = 0; + for (vector::size_type i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + + int space_needed = + argv_array_size + + envp_array_size + + auxv_array_size + + arg_data_size + + env_data_size; + + if (space_needed < 32*1024) + space_needed = 32*1024; + + // set bottom of stack + stack_min = stack_base - space_needed; + // align it + stack_min = roundDown(stack_min, pageSize); + stack_size = stack_base - stack_min; + // map memory + allocateMem(stack_min, roundUp(stack_size, pageSize)); + + // map out initial stack contents + Addr argv_array_base = stack_min + intSize; // room for argc + Addr envp_array_base = argv_array_base + argv_array_size; + Addr auxv_array_base = envp_array_base + envp_array_size; + Addr arg_data_base = auxv_array_base + auxv_array_size; + Addr env_data_base = arg_data_base + arg_data_size; + + // write contents to stack + uint64_t argc = argv.size(); + if (intSize == 8) + argc = htog((uint64_t)argc); + else if (intSize == 4) + argc = htog((uint32_t)argc); + else + panic("Unknown int size"); + + initVirtMem.writeBlob(stack_min, (uint8_t*)&argc, intSize); + + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + + //Copy the aux stuff + for (vector::size_type x = 0; x < auxv.size(); x++) { + initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + + ThreadContext *tc = system->getThreadContext(contextIds[0]); + + setSyscallArg(tc, 0, argc); + setSyscallArg(tc, 1, argv_array_base); + tc->setIntReg(StackPointerReg, stack_min); + + tc->pcState(objFile->entryPoint()); +} + +void +AlphaLiveProcess::setupASNReg() +{ + ThreadContext *tc = system->getThreadContext(contextIds[0]); + tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); +} + + +void +AlphaLiveProcess::loadState(Checkpoint *cp) +{ + LiveProcess::loadState(cp); + // need to set up ASN after unserialization since M5_pid value may + // come from checkpoint + setupASNReg(); +} + + +void +AlphaLiveProcess::initState() +{ + // need to set up ASN before further initialization since init + // will involve writing to virtual memory addresses + setupASNReg(); + + LiveProcess::initState(); + + argsInit(MachineBytes, VMPageSize); + + ThreadContext *tc = system->getThreadContext(contextIds[0]); + tc->setIntReg(GlobalPointerReg, objFile->globalPointer()); + //Operate in user mode + tc->setMiscRegNoEffect(IPR_ICM, mode_user << 3); + tc->setMiscRegNoEffect(IPR_DTB_CM, mode_user << 3); + //No super page mapping + tc->setMiscRegNoEffect(IPR_MCSR, 0); +} + +AlphaISA::IntReg +AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int &i) +{ + assert(i < 6); + return tc->readIntReg(FirstArgumentReg + i++); +} + +void +AlphaLiveProcess::setSyscallArg(ThreadContext *tc, + int i, AlphaISA::IntReg val) +{ + assert(i < 6); + tc->setIntReg(FirstArgumentReg + i, val); +} + +void +AlphaLiveProcess::setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) +{ + // check for error condition. Alpha syscall convention is to + // indicate success/failure in reg a3 (r19) and put the + // return value itself in the standard return value reg (v0). + if (return_value.successful()) { + // no error + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + tc->setIntReg(SyscallSuccessReg, (IntReg)-1); + tc->setIntReg(ReturnValueReg, -return_value.value()); + } +} diff --git a/simulators/gem5/src/arch/alpha/process.hh b/simulators/gem5/src/arch/alpha/process.hh new file mode 100644 index 00000000..40d6bf48 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/process.hh @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_ALPHA_PROCESS_HH__ +#define __ARCH_ALPHA_PROCESS_HH__ + +#include "sim/process.hh" + +class AlphaLiveProcess : public LiveProcess +{ + private: + void setupASNReg(); + + protected: + AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile); + + void loadState(Checkpoint *cp); + void initState(); + + void argsInit(int intSize, int pageSize); + + public: + AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int &i); + void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val); + void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); +}; + +#endif // __ARCH_ALPHA_PROCESS_HH__ diff --git a/simulators/gem5/src/arch/alpha/registers.hh b/simulators/gem5/src/arch/alpha/registers.hh new file mode 100644 index 00000000..e1f50ddc --- /dev/null +++ b/simulators/gem5/src/arch/alpha/registers.hh @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ALPHA_REGISTERS_HH__ +#define __ARCH_ALPHA_REGISTERS_HH__ + +#include "arch/alpha/generated/max_inst_regs.hh" +#include "arch/alpha/ipr.hh" +#include "base/types.hh" + +namespace AlphaISA { + +using AlphaISAInst::MaxInstSrcRegs; +using AlphaISAInst::MaxInstDestRegs; + +// Locked read/write flags are can't be detected by the ISA parser +const int MaxMiscDestRegs = AlphaISAInst::MaxMiscDestRegs + 1; + +typedef uint8_t RegIndex; +typedef uint64_t IntReg; + +// floating point register file entry type +typedef double FloatReg; +typedef uint64_t FloatRegBits; + +// control register file contents +typedef uint64_t MiscReg; + +union AnyReg +{ + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; +}; + +enum MiscRegIndex +{ + MISCREG_FPCR = NumInternalProcRegs, + MISCREG_UNIQ, + MISCREG_LOCKFLAG, + MISCREG_LOCKADDR, + MISCREG_INTR, + NUM_MISCREGS +}; + +// semantically meaningful register indices +const RegIndex ZeroReg = 31; // architecturally meaningful +// the rest of these depend on the ABI +const RegIndex StackPointerReg = 30; +const RegIndex GlobalPointerReg = 29; +const RegIndex ProcedureValueReg = 27; +const RegIndex ReturnAddressReg = 26; +const RegIndex ReturnValueReg = 0; +const RegIndex FramePointerReg = 15; + +const RegIndex SyscallNumReg = 0; +const RegIndex FirstArgumentReg = 16; +const RegIndex SyscallPseudoReturnReg = 20; +const RegIndex SyscallSuccessReg = 19; + +const int NumIntArchRegs = 32; +const int NumPALShadowRegs = 8; +const int NumFloatArchRegs = 32; +const int NumMiscArchRegs = NUM_MISCREGS; + +const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; +const int NumFloatRegs = NumFloatArchRegs; +const int NumMiscRegs = NumMiscArchRegs; + +const int TotalNumRegs = + NumIntRegs + NumFloatRegs + NumMiscRegs; + +const int TotalDataRegs = NumIntRegs + NumFloatRegs; + +// These enumerate all the registers for dependence tracking. +enum DependenceTags { + // 0..31 are the integer regs 0..31 + // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = 40, + Ctrl_Base_DepTag = 72, + Max_DepTag = Ctrl_Base_DepTag + NumMiscRegs + NumInternalProcRegs +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_REGFILE_HH__ diff --git a/simulators/gem5/src/arch/alpha/regredir.cc b/simulators/gem5/src/arch/alpha/regredir.cc new file mode 100644 index 00000000..861ded4d --- /dev/null +++ b/simulators/gem5/src/arch/alpha/regredir.cc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003-2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Gabe Black + * Kevin Lim + */ + +#include "arch/alpha/regredir.hh" + +namespace AlphaISA { + +const int reg_redir[NumIntRegs] = { + /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, + /* 8 */ 32, 33, 34, 35, 36, 37, 38, 15, + /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, + /* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 }; + +} // namespace AlphaISA diff --git a/simulators/gem5/src/arch/alpha/regredir.hh b/simulators/gem5/src/arch/alpha/regredir.hh new file mode 100644 index 00000000..6e12be41 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/regredir.hh @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003-2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ALPHA_REGREDIR_HH__ +#define __ARCH_ALPHA_REGREDIR_HH__ + +#include "arch/alpha/registers.hh" + +namespace AlphaISA { + +// redirected register map, really only used for the full system case. +extern const int reg_redir[NumIntRegs]; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_REGREDIR_HH__ diff --git a/simulators/gem5/src/arch/alpha/remote_gdb.cc b/simulators/gem5/src/arch/alpha/remote_gdb.cc new file mode 100644 index 00000000..21464fda --- /dev/null +++ b/simulators/gem5/src/arch/alpha/remote_gdb.cc @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +/* + * Copyright (c) 1990, 1993 The Regents of the University of California + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ + * + * Taken from NetBSD + * + * "Stub" to allow remote cpu to debug over a serial line using gdb. + */ + +#include +#include + +#include + + +#include "arch/alpha/decoder.hh" +#include "arch/alpha/kgdb.h" +#include "arch/alpha/regredir.hh" +#include "arch/alpha/remote_gdb.hh" +#include "arch/alpha/utility.hh" +#include "arch/alpha/vtophys.hh" +#include "base/intmath.hh" +#include "base/remote_gdb.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "cpu/static_inst.hh" +#include "cpu/thread_context.hh" +#include "debug/GDBAcc.hh" +#include "debug/GDBMisc.hh" +#include "mem/physical.hh" +#include "mem/port.hh" +#include "sim/system.hh" +#include "sim/full_system.hh" + +using namespace std; +using namespace AlphaISA; + +RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) + : BaseRemoteGDB(_system, tc, KGDB_NUMREGS) +{ + memset(gdbregs.regs, 0, gdbregs.bytes()); +} + +/* + * Determine if the mapping at va..(va+len) is valid. + */ +bool +RemoteGDB::acc(Addr va, size_t len) +{ + if (!FullSystem) + panic("acc function needs to be rewritten for SE mode\n"); + + Addr last_va; + + va = TruncPage(va); + last_va = RoundPage(va + len); + + do { + if (IsK0Seg(va)) { + if (va < (K0SegBase + system->memSize())) { + DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " + "%#x < K0SEG + size\n", va); + return true; + } else { + DPRINTF(GDBAcc, "acc: Mapping invalid %#x " + "> K0SEG + size\n", va); + return false; + } + } + + /** + * This code says that all accesses to palcode (instruction + * and data) are valid since there isn't a va->pa mapping + * because palcode is accessed physically. At some point this + * should probably be cleaned up but there is no easy way to + * do it. + */ + + if (PcPAL(va) || va < 0x10000) + return true; + + Addr ptbr = context->readMiscRegNoEffect(IPR_PALtemp20); + PageTableEntry pte = + kernel_pte_lookup(context->getPhysProxy(), ptbr, va); + if (!pte.valid()) { + DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); + return false; + } + va += PageBytes; + } while (va < last_va); + + DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); + return true; +} + +/* + * Translate the kernel debugger register format into the GDB register + * format. + */ +void +RemoteGDB::getregs() +{ + memset(gdbregs.regs, 0, gdbregs.bytes()); + + gdbregs.regs[KGDB_REG_PC] = context->pcState().pc(); + + // @todo: Currently this is very Alpha specific. + if (PcPAL(gdbregs.regs[KGDB_REG_PC])) { + for (int i = 0; i < NumIntArchRegs; ++i) { + gdbregs.regs[i] = context->readIntReg(reg_redir[i]); + } + } else { + for (int i = 0; i < NumIntArchRegs; ++i) { + gdbregs.regs[i] = context->readIntReg(i); + } + } + +#ifdef KGDB_FP_REGS + for (int i = 0; i < NumFloatArchRegs; ++i) { + gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i); + } +#endif +} + +/* + * Translate the GDB register format into the kernel debugger register + * format. + */ +void +RemoteGDB::setregs() +{ + // @todo: Currently this is very Alpha specific. + if (PcPAL(gdbregs.regs[KGDB_REG_PC])) { + for (int i = 0; i < NumIntArchRegs; ++i) { + context->setIntReg(reg_redir[i], gdbregs.regs[i]); + } + } else { + for (int i = 0; i < NumIntArchRegs; ++i) { + context->setIntReg(i, gdbregs.regs[i]); + } + } + +#ifdef KGDB_FP_REGS + for (int i = 0; i < NumFloatArchRegs; ++i) { + context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]); + } +#endif + context->pcState(gdbregs.regs[KGDB_REG_PC]); +} + +void +RemoteGDB::clearSingleStep() +{ + DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n", + takenBkpt, notTakenBkpt); + + if (takenBkpt != 0) + clearTempBreakpoint(takenBkpt); + + if (notTakenBkpt != 0) + clearTempBreakpoint(notTakenBkpt); +} + +void +RemoteGDB::setSingleStep() +{ + PCState pc = context->pcState(); + PCState bpc; + bool set_bt = false; + + // User was stopped at pc, e.g. the instruction at pc was not + // executed. + MachInst inst = read(pc.pc()); + StaticInstPtr si = context->getDecoderPtr()->decode(inst, pc.pc()); + if (si->hasBranchTarget(pc, context, bpc)) { + // Don't bother setting a breakpoint on the taken branch if it + // is the same as the next pc + if (bpc.pc() != pc.npc()) + set_bt = true; + } + + DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n", + takenBkpt, notTakenBkpt); + + setTempBreakpoint(notTakenBkpt = pc.npc()); + + if (set_bt) + setTempBreakpoint(takenBkpt = bpc.pc()); +} + +// Write bytes to kernel address space for debugger. +bool +RemoteGDB::write(Addr vaddr, size_t size, const char *data) +{ + if (BaseRemoteGDB::write(vaddr, size, data)) { +#ifdef IMB + alpha_pal_imb(); +#endif + return true; + } else { + return false; + } +} + + +bool +RemoteGDB::insertHardBreak(Addr addr, size_t len) +{ + warn_once("Breakpoints do not work in Alpha PAL mode.\n" + " See PCEventQueue::doService() in cpu/pc_event.cc.\n"); + return BaseRemoteGDB::insertHardBreak(addr, len); +} diff --git a/simulators/gem5/src/arch/alpha/remote_gdb.hh b/simulators/gem5/src/arch/alpha/remote_gdb.hh new file mode 100644 index 00000000..d9c124c7 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/remote_gdb.hh @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ +#define __ARCH_ALPHA_REMOTE_GDB_HH__ + +#include + +#include "arch/alpha/kgdb.h" +#include "arch/alpha/types.hh" +#include "base/pollevent.hh" +#include "base/remote_gdb.hh" +#include "base/socket.hh" +#include "cpu/pc_event.hh" + +class System; +class ThreadContext; + +namespace AlphaISA { + +class RemoteGDB : public BaseRemoteGDB +{ + protected: + Addr notTakenBkpt; + Addr takenBkpt; + + protected: + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + + // Machine memory + bool acc(Addr addr, size_t len); + bool write(Addr addr, size_t size, const char *data); + + virtual bool insertHardBreak(Addr addr, size_t len); + + public: + RemoteGDB(System *system, ThreadContext *context); +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_REMOTE_GDB_HH__ diff --git a/simulators/gem5/src/arch/alpha/stacktrace.cc b/simulators/gem5/src/arch/alpha/stacktrace.cc new file mode 100644 index 00000000..7c23489a --- /dev/null +++ b/simulators/gem5/src/arch/alpha/stacktrace.cc @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/stacktrace.hh" +#include "arch/alpha/vtophys.hh" +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "sim/system.hh" + +using namespace std; + +namespace AlphaISA { + +ProcessInfo::ProcessInfo(ThreadContext *_tc) + : tc(_tc) +{ + Addr addr = 0; + FSTranslatingPortProxy &vp = tc->getVirtProxy(); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + + if (!symtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = vp.readGtoH(addr); + + if (!symtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = vp.readGtoH(addr); + + if (!symtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = vp.readGtoH(addr); + + if (!symtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = vp.readGtoH(addr); + + if (!symtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = vp.readGtoH(addr); +} + +Addr +ProcessInfo::task(Addr ksp) const +{ + Addr base = ksp & ~0x3fff; + if (base == ULL(0xfffffc0000000000)) + return 0; + + Addr tsk; + + FSTranslatingPortProxy &vp = tc->getVirtProxy(); + tsk = vp.readGtoH(base + task_off); + + return tsk; +} + +int +ProcessInfo::pid(Addr ksp) const +{ + Addr task = this->task(ksp); + if (!task) + return -1; + + uint16_t pd; + + FSTranslatingPortProxy &vp = tc->getVirtProxy(); + pd = vp.readGtoH(task + pid_off); + + return pd; +} + +string +ProcessInfo::name(Addr ksp) const +{ + Addr task = this->task(ksp); + if (!task) + return "console"; + + char comm[256]; + CopyStringOut(tc, comm, task + name_off, sizeof(comm)); + if (!comm[0]) + return "startup"; + + return comm; +} + +StackTrace::StackTrace() + : tc(0), stack(64) +{ +} + +StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) + : tc(0), stack(64) +{ + trace(_tc, inst); +} + +StackTrace::~StackTrace() +{ +} + +void +StackTrace::trace(ThreadContext *_tc, bool is_call) +{ + tc = _tc; + + System *sys = tc->getSystemPtr(); + + bool usermode = + (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; + + Addr pc = tc->pcState().pc(); + bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd; + + if (usermode) { + stack.push_back(user); + return; + } + + if (!kernel) { + stack.push_back(console); + return; + } + + SymbolTable *symtab = sys->kernelSymtab; + Addr ksp = tc->readIntReg(StackPointerReg); + Addr bottom = ksp & ~0x3fff; + + if (is_call) { + Addr addr; + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find address %#x", pc); + + stack.push_back(addr); + pc = tc->pcState().pc(); + } + + while (ksp > bottom) { + Addr addr; + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find symbol for pc=%#x", pc); + assert(pc >= addr && "symbol botch: callpc < func"); + + stack.push_back(addr); + + if (isEntry(addr)) + return; + + Addr ra; + int size; + if (decodePrologue(ksp, pc, addr, size, ra)) { + if (!ra) + return; + + if (size <= 0) { + stack.push_back(unknown); + return; + } + + pc = ra; + ksp += size; + } else { + stack.push_back(unknown); + return; + } + + bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd; + if (!kernel) + return; + + if (stack.size() >= 1000) + panic("unwinding too far"); + } + + panic("unwinding too far"); +} + +bool +StackTrace::isEntry(Addr addr) +{ + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12)) + return true; + + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7)) + return true; + + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11)) + return true; + + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21)) + return true; + + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9)) + return true; + + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2)) + return true; + + return false; +} + +bool +StackTrace::decodeStack(MachInst inst, int &disp) +{ + // lda $sp, -disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == 30 + // RB<20:16> == 30 + // Disp<15:0> + const MachInst mem_mask = 0xffff0000; + const MachInst lda_pattern = 0x23de0000; + const MachInst lda_disp_mask = 0x0000ffff; + + // subq $sp, disp, $sp + // addq $sp, disp, $sp + // + // Opcode<31:26> == 0x10 + // RA<25:21> == 30 + // Lit<20:13> + // One<12> = 1 + // Func<11:5> == 0x20 (addq) + // Func<11:5> == 0x29 (subq) + // RC<4:0> == 30 + const MachInst intop_mask = 0xffe01fff; + const MachInst addq_pattern = 0x43c0141e; + const MachInst subq_pattern = 0x43c0153e; + const MachInst intop_disp_mask = 0x001fe000; + const int intop_disp_shift = 13; + + if ((inst & mem_mask) == lda_pattern) + disp = -sext<16>(inst & lda_disp_mask); + else if ((inst & intop_mask) == addq_pattern) + disp = -int((inst & intop_disp_mask) >> intop_disp_shift); + else if ((inst & intop_mask) == subq_pattern) + disp = int((inst & intop_disp_mask) >> intop_disp_shift); + else + return false; + + return true; +} + +bool +StackTrace::decodeSave(MachInst inst, int ®, int &disp) +{ + // lda $stq, disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == ? + // RB<20:16> == 30 + // Disp<15:0> + const MachInst stq_mask = 0xfc1f0000; + const MachInst stq_pattern = 0xb41e0000; + const MachInst stq_disp_mask = 0x0000ffff; + const MachInst reg_mask = 0x03e00000; + const int reg_shift = 21; + + if ((inst & stq_mask) == stq_pattern) { + reg = (inst & reg_mask) >> reg_shift; + disp = sext<16>(inst & stq_disp_mask); + } else { + return false; + } + + return true; +} + +/* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ +bool +StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, int &size, + Addr &ra) +{ + size = 0; + ra = 0; + + for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { + MachInst inst; + CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); + + int reg, disp; + if (decodeStack(inst, disp)) { + if (size) { + // panic("decoding frame size again"); + return true; + } + size += disp; + } else if (decodeSave(inst, reg, disp)) { + if (!ra && reg == ReturnAddressReg) { + CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); + if (!ra) { + // panic("no return address value pc=%#x\n", pc); + return false; + } + } + } + } + + return true; +} + +#if TRACING_ON +void +StackTrace::dump() +{ + StringWrap name(tc->getCpuPtr()->name()); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + + DPRINTFN("------ Stack ------\n"); + + string symbol; + for (int i = 0, size = stack.size(); i < size; ++i) { + Addr addr = stack[size - i - 1]; + if (addr == user) + symbol = "user"; + else if (addr == console) + symbol = "console"; + else if (addr == unknown) + symbol = "unknown"; + else + symtab->findSymbol(addr, symbol); + + DPRINTFN("%#x: %s\n", addr, symbol); + } +} +#endif + +} // namespace AlphaISA diff --git a/simulators/gem5/src/arch/alpha/stacktrace.hh b/simulators/gem5/src/arch/alpha/stacktrace.hh new file mode 100644 index 00000000..669c6578 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/stacktrace.hh @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_STACKTRACE_HH__ +#define __ARCH_ALPHA_STACKTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" +#include "debug/Stack.hh" + +class ThreadContext; + +namespace AlphaISA { + +class StackTrace; + +class ProcessInfo +{ + private: + ThreadContext *tc; + + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; + + public: + ProcessInfo(ThreadContext *_tc); + + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; +}; + +class StackTrace +{ + private: + ThreadContext *tc; + std::vector stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + void trace(ThreadContext *tc, bool is_call); + + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); + + void + clear() + { + tc = 0; + stack.clear(); + } + + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector &getstack() const { return stack; } + + enum { + user = 1, + console = 2, + unknown = 3 + }; + +#if TRACING_ON + private: + void dump(); + + public: + void dprintf() { if (DTRACE(Stack)) dump(); } +#else + public: + void dprintf() {} +#endif +}; + +inline bool +StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) +{ + if (!inst->isCall() && !inst->isReturn()) + return false; + + if (valid()) + clear(); + + trace(tc, !inst->isReturn()); + return true; +} + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_STACKTRACE_HH__ diff --git a/simulators/gem5/src/arch/alpha/system.cc b/simulators/gem5/src/arch/alpha/system.cc new file mode 100644 index 00000000..51e1d7e0 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/system.cc @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Nathan Binkert + */ + +#include + +#include "arch/alpha/ev5.hh" +#include "arch/alpha/system.hh" +#include "arch/vtophys.hh" +#include "base/loader/object_file.hh" +#include "base/loader/symtab.hh" +#include "base/trace.hh" +#include "debug/Loader.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "params/AlphaSystem.hh" +#include "sim/byteswap.hh" + +using namespace AlphaISA; + +AlphaSystem::AlphaSystem(Params *p) + : System(p), intrFreq(0) +{ + consoleSymtab = new SymbolTable; + palSymtab = new SymbolTable; + + + /** + * Load the pal, and console code into memory + */ + // Load Console Code + console = createObjectFile(params()->console); + if (console == NULL) + fatal("Could not load console file %s", params()->console); + + // Load pal file + pal = createObjectFile(params()->pal); + if (pal == NULL) + fatal("Could not load PALcode file %s", params()->pal); + + // load symbols + if (!console->loadGlobalSymbols(consoleSymtab)) + panic("could not load console symbols\n"); + + if (!pal->loadGlobalSymbols(palSymtab)) + panic("could not load pal symbols\n"); + + if (!pal->loadLocalSymbols(palSymtab)) + panic("could not load pal symbols\n"); + + if (!console->loadGlobalSymbols(debugSymbolTable)) + panic("could not load console symbols\n"); + + if (!pal->loadGlobalSymbols(debugSymbolTable)) + panic("could not load pal symbols\n"); + + if (!pal->loadLocalSymbols(debugSymbolTable)) + panic("could not load pal symbols\n"); + + +} + +AlphaSystem::~AlphaSystem() +{ + delete consoleSymtab; + delete console; + delete pal; +#ifdef DEBUG + delete consolePanicEvent; +#endif +} + +void +AlphaSystem::initState() +{ + Addr addr = 0; + + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + + // Call the initialisation of the super class + System::initState(); + + // Load program sections into memory + pal->loadSections(physProxy, loadAddrMask); + console->loadSections(physProxy, loadAddrMask); + + /** + * Copy the osflags (kernel arguments) into the consoles + * memory. (Presently Linux does not use the console service + * routine to get these command line arguments, but Tru64 and + * others do.) + */ + if (consoleSymtab->findAddress("env_booted_osflags", addr)) { + virtProxy.writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(), + strlen(params()->boot_osflags.c_str())); + } + + /** + * Set the hardware reset parameter block system type and revision + * information to Tsunami. + */ + if (consoleSymtab->findAddress("m5_rpb", addr)) { + uint64_t data; + data = htog(params()->system_type); + virtProxy.write(addr+0x50, data); + data = htog(params()->system_rev); + virtProxy.write(addr+0x58, data); + } else + panic("could not find hwrpb\n"); + + // Setup all the function events now that we have a system and a symbol + // table + setupFuncEvents(); +} + +void +AlphaSystem::loadState(Checkpoint *cp) +{ + System::loadState(cp); + + // Setup all the function events now that we have a system and a symbol + // table + setupFuncEvents(); + +} + +void +AlphaSystem::setupFuncEvents() +{ +#ifndef NDEBUG + consolePanicEvent = addConsoleFuncEvent("panic"); +#endif +} + +/** + * This function fixes up addresses that are used to match PCs for + * hooking simulator events on to target function executions. + * + * Alpha binaries may have multiple global offset table (GOT) + * sections. A function that uses the GOT starts with a + * two-instruction prolog which sets the global pointer (gp == r29) to + * the appropriate GOT section. The proper gp value is calculated + * based on the function address, which must be passed by the caller + * in the procedure value register (pv aka t12 == r27). This sequence + * looks like the following: + * + * opcode Ra Rb offset + * ldah gp,X(pv) 09 29 27 X + * lda gp,Y(gp) 08 29 29 Y + * + * for some constant offsets X and Y. The catch is that the linker + * (or maybe even the compiler, I'm not sure) may recognize that the + * caller and callee are using the same GOT section, making this + * prolog redundant, and modify the call target to skip these + * instructions. If we check for execution of the first instruction + * of a function (the one the symbol points to) to detect when to skip + * it, we'll miss all these modified calls. It might work to + * unconditionally check for the third instruction, but not all + * functions have this prolog, and there's some chance that those + * first two instructions could have undesired consequences. So we do + * the Right Thing and pattern-match the first two instructions of the + * function to decide where to patch. + * + * Eventually this code should be moved into an ISA-specific file. + */ +Addr +AlphaSystem::fixFuncEventAddr(Addr addr) +{ + // mask for just the opcode, Ra, and Rb fields (not the offset) + const uint32_t inst_mask = 0xffff0000; + // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27 + const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16); + // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 + const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); + + uint32_t i1 = virtProxy.read(addr); + uint32_t i2 = virtProxy.read(addr + sizeof(MachInst)); + + if ((i1 & inst_mask) == gp_ldah_pattern && + (i2 & inst_mask) == gp_lda_pattern) { + Addr new_addr = addr + 2 * sizeof(MachInst); + DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); + return new_addr; + } else { + return addr; + } +} + +void +AlphaSystem::setAlphaAccess(Addr access) +{ + Addr addr = 0; + if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { + virtProxy.write(addr, htog(Phys2K0Seg(access))); + } else { + panic("could not find m5AlphaAccess\n"); + } +} + +void +AlphaSystem::serialize(std::ostream &os) +{ + System::serialize(os); + consoleSymtab->serialize("console_symtab", os); + palSymtab->serialize("pal_symtab", os); +} + +void +AlphaSystem::unserialize(Checkpoint *cp, const std::string §ion) +{ + System::unserialize(cp,section); + consoleSymtab->unserialize("console_symtab", cp, section); + palSymtab->unserialize("pal_symtab", cp, section); +} + +AlphaSystem * +AlphaSystemParams::create() +{ + return new AlphaSystem(this); +} diff --git a/simulators/gem5/src/arch/alpha/system.hh b/simulators/gem5/src/arch/alpha/system.hh new file mode 100644 index 00000000..d832dfe7 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/system.hh @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_SYSTEM_HH__ +#define __ARCH_ALPHA_SYSTEM_HH__ + +#include +#include + +#include "base/loader/symtab.hh" +#include "cpu/pc_event.hh" +#include "kern/system_events.hh" +#include "params/AlphaSystem.hh" +#include "sim/sim_object.hh" +#include "sim/system.hh" + +class AlphaSystem : public System +{ + public: + typedef AlphaSystemParams Params; + AlphaSystem(Params *p); + ~AlphaSystem(); + + public: + + /** + * Initialise the state of the system. + */ + virtual void initState(); + + /** + * Serialization stuff + */ + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + /** Override loadState to provide a path to call setupFuncEvents() + */ + virtual void loadState(Checkpoint *cp); + + /** + * Set the m5AlphaAccess pointer in the console + */ + void setAlphaAccess(Addr access); + + /** console symbol table */ + SymbolTable *consoleSymtab; + + /** pal symbol table */ + SymbolTable *palSymtab; + + /** Object pointer for the console code */ + ObjectFile *console; + + /** Object pointer for the PAL code */ + ObjectFile *pal; + +#ifndef NDEBUG + /** Event to halt the simulator if the console calls panic() */ + BreakPCEvent *consolePanicEvent; +#endif + + protected: + Tick intrFreq; + + const Params *params() const { return (const Params *)_params; } + + + /** Setup all the function events. Must be done after init() for Alpha since + * fixFuncEvent() requires a function port + */ + virtual void setupFuncEvents(); + + /** Add a function-based event to PALcode. */ + template + T * + addPalFuncEvent(const char *lbl) + { + return addFuncEvent(palSymtab, lbl); + } + + /** Add a function-based event to the console code. */ + template + T * + addConsoleFuncEvent(const char *lbl) + { + return addFuncEvent(consoleSymtab, lbl); + } + + virtual Addr fixFuncEventAddr(Addr addr); + + public: + void setIntrFreq(Tick freq) { intrFreq = freq; } +}; + +#endif // __ARCH_ALPHA_SYSTEM_HH__ + diff --git a/simulators/gem5/src/arch/alpha/tlb.cc b/simulators/gem5/src/arch/alpha/tlb.cc new file mode 100644 index 00000000..1d18c8d3 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tlb.cc @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + * Andrew Schultz + */ + +#include +#include + +#include "arch/alpha/faults.hh" +#include "arch/alpha/pagetable.hh" +#include "arch/alpha/tlb.hh" +#include "arch/generic/debugfaults.hh" +#include "base/inifile.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/TLB.hh" +#include "sim/full_system.hh" + +using namespace std; + +namespace AlphaISA { + +/////////////////////////////////////////////////////////////////////// +// +// Alpha TLB +// + +#ifdef DEBUG +bool uncacheBit39 = false; +bool uncacheBit40 = false; +#endif + +#define MODE2MASK(X) (1 << (X)) + +TLB::TLB(const Params *p) + : BaseTLB(p), size(p->size), nlu(0) +{ + table = new TlbEntry[size]; + memset(table, 0, sizeof(TlbEntry) * size); + flushCache(); +} + +TLB::~TLB() +{ + if (table) + delete [] table; +} + +void +TLB::regStats() +{ + fetch_hits + .name(name() + ".fetch_hits") + .desc("ITB hits"); + fetch_misses + .name(name() + ".fetch_misses") + .desc("ITB misses"); + fetch_acv + .name(name() + ".fetch_acv") + .desc("ITB acv"); + fetch_accesses + .name(name() + ".fetch_accesses") + .desc("ITB accesses"); + + fetch_accesses = fetch_hits + fetch_misses; + + read_hits + .name(name() + ".read_hits") + .desc("DTB read hits") + ; + + read_misses + .name(name() + ".read_misses") + .desc("DTB read misses") + ; + + read_acv + .name(name() + ".read_acv") + .desc("DTB read access violations") + ; + + read_accesses + .name(name() + ".read_accesses") + .desc("DTB read accesses") + ; + + write_hits + .name(name() + ".write_hits") + .desc("DTB write hits") + ; + + write_misses + .name(name() + ".write_misses") + .desc("DTB write misses") + ; + + write_acv + .name(name() + ".write_acv") + .desc("DTB write access violations") + ; + + write_accesses + .name(name() + ".write_accesses") + .desc("DTB write accesses") + ; + + data_hits + .name(name() + ".data_hits") + .desc("DTB hits") + ; + + data_misses + .name(name() + ".data_misses") + .desc("DTB misses") + ; + + data_acv + .name(name() + ".data_acv") + .desc("DTB access violations") + ; + + data_accesses + .name(name() + ".data_accesses") + .desc("DTB accesses") + ; + + data_hits = read_hits + write_hits; + data_misses = read_misses + write_misses; + data_acv = read_acv + write_acv; + data_accesses = read_accesses + write_accesses; +} + +// look up an entry in the TLB +TlbEntry * +TLB::lookup(Addr vpn, uint8_t asn) +{ + // assume not found... + TlbEntry *retval = NULL; + + if (EntryCache[0]) { + if (vpn == EntryCache[0]->tag && + (EntryCache[0]->asma || EntryCache[0]->asn == asn)) + retval = EntryCache[0]; + else if (EntryCache[1]) { + if (vpn == EntryCache[1]->tag && + (EntryCache[1]->asma || EntryCache[1]->asn == asn)) + retval = EntryCache[1]; + else if (EntryCache[2] && vpn == EntryCache[2]->tag && + (EntryCache[2]->asma || EntryCache[2]->asn == asn)) + retval = EntryCache[2]; + } + } + + if (retval == NULL) { + PageTable::const_iterator i = lookupTable.find(vpn); + if (i != lookupTable.end()) { + while (i->first == vpn) { + int index = i->second; + TlbEntry *entry = &table[index]; + assert(entry->valid); + if (vpn == entry->tag && (entry->asma || entry->asn == asn)) { + retval = updateCache(entry); + break; + } + + ++i; + } + } + } + + DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, + retval ? "hit" : "miss", retval ? retval->ppn : 0); + return retval; +} + +Fault +TLB::checkCacheability(RequestPtr &req, bool itb) +{ + // in Alpha, cacheability is controlled by upper-level bits of the + // physical address + + /* + * We support having the uncacheable bit in either bit 39 or bit + * 40. The Turbolaser platform (and EV5) support having the bit + * in 39, but Tsunami (which Linux assumes uses an EV6) generates + * accesses with the bit in 40. So we must check for both, but we + * have debug flags to catch a weird case where both are used, + * which shouldn't happen. + */ + + + if (req->getPaddr() & PAddrUncachedBit43) { + // IPR memory space not implemented + if (PAddrIprSpace(req->getPaddr())) { + return new UnimpFault("IPR memory space not implemented!"); + } else { + // mark request as uncacheable + req->setFlags(Request::UNCACHEABLE); + + // Clear bits 42:35 of the physical address (10-2 in + // Tsunami manual) + req->setPaddr(req->getPaddr() & PAddrUncachedMask); + } + // We shouldn't be able to read from an uncachable address in Alpha as + // we don't have a ROM and we don't want to try to fetch from a device + // register as we destroy any data that is clear-on-read. + if (req->isUncacheable() && itb) + return new UnimpFault("CPU trying to fetch from uncached I/O"); + + } + return NoFault; +} + + +// insert a new TLB entry +void +TLB::insert(Addr addr, TlbEntry &entry) +{ + flushCache(); + VAddr vaddr = addr; + if (table[nlu].valid) { + Addr oldvpn = table[nlu].tag; + PageTable::iterator i = lookupTable.find(oldvpn); + + if (i == lookupTable.end()) + panic("TLB entry not found in lookupTable"); + + int index; + while ((index = i->second) != nlu) { + if (table[index].tag != oldvpn) + panic("TLB entry not found in lookupTable"); + + ++i; + } + + DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); + + lookupTable.erase(i); + } + + DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), entry.ppn); + + table[nlu] = entry; + table[nlu].tag = vaddr.vpn(); + table[nlu].valid = true; + + lookupTable.insert(make_pair(vaddr.vpn(), nlu)); + nextnlu(); +} + +void +TLB::flushAll() +{ + DPRINTF(TLB, "flushAll\n"); + memset(table, 0, sizeof(TlbEntry) * size); + flushCache(); + lookupTable.clear(); + nlu = 0; +} + +void +TLB::flushProcesses() +{ + flushCache(); + PageTable::iterator i = lookupTable.begin(); + PageTable::iterator end = lookupTable.end(); + while (i != end) { + int index = i->second; + TlbEntry *entry = &table[index]; + assert(entry->valid); + + // we can't increment i after we erase it, so save a copy and + // increment it to get the next entry now + PageTable::iterator cur = i; + ++i; + + if (!entry->asma) { + DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, + entry->tag, entry->ppn); + entry->valid = false; + lookupTable.erase(cur); + } + } +} + +void +TLB::flushAddr(Addr addr, uint8_t asn) +{ + flushCache(); + VAddr vaddr = addr; + + PageTable::iterator i = lookupTable.find(vaddr.vpn()); + if (i == lookupTable.end()) + return; + + while (i != lookupTable.end() && i->first == vaddr.vpn()) { + int index = i->second; + TlbEntry *entry = &table[index]; + assert(entry->valid); + + if (vaddr.vpn() == entry->tag && (entry->asma || entry->asn == asn)) { + DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), + entry->ppn); + + // invalidate this entry + entry->valid = false; + + lookupTable.erase(i++); + } else { + ++i; + } + } +} + + +void +TLB::serialize(ostream &os) +{ + SERIALIZE_SCALAR(size); + SERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + nameOut(os, csprintf("%s.Entry%d", name(), i)); + table[i].serialize(os); + } +} + +void +TLB::unserialize(Checkpoint *cp, const string §ion) +{ + UNSERIALIZE_SCALAR(size); + UNSERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + table[i].unserialize(cp, csprintf("%s.Entry%d", section, i)); + if (table[i].valid) { + lookupTable.insert(make_pair(table[i].tag, i)); + } + } +} + +Fault +TLB::translateInst(RequestPtr req, ThreadContext *tc) +{ + //If this is a pal pc, then set PHYSICAL + if (FullSystem && PcPAL(req->getPC())) + req->setFlags(Request::PHYSICAL); + + if (PcPAL(req->getPC())) { + // strip off PAL PC marker (lsb is 1) + req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); + fetch_hits++; + return NoFault; + } + + if (req->getFlags() & Request::PHYSICAL) { + req->setPaddr(req->getVaddr()); + } else { + // verify that this is a good virtual address + if (!validVirtualAddress(req->getVaddr())) { + fetch_acv++; + return new ItbAcvFault(req->getVaddr()); + } + + + // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 + // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { + // only valid in kernel mode + if (ICM_CM(tc->readMiscRegNoEffect(IPR_ICM)) != + mode_kernel) { + fetch_acv++; + return new ItbAcvFault(req->getVaddr()); + } + + req->setPaddr(req->getVaddr() & PAddrImplMask); + + // sign extend the physical address properly + if (req->getPaddr() & PAddrUncachedBit40) + req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); + else + req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); + } else { + // not a physical address: need to look up pte + int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); + TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), + asn); + + if (!entry) { + fetch_misses++; + return new ItbPageFault(req->getVaddr()); + } + + req->setPaddr((entry->ppn << PageShift) + + (VAddr(req->getVaddr()).offset() + & ~3)); + + // check permissions for this access + if (!(entry->xre & + (1 << ICM_CM(tc->readMiscRegNoEffect(IPR_ICM))))) { + // instruction access fault + fetch_acv++; + return new ItbAcvFault(req->getVaddr()); + } + + fetch_hits++; + } + } + + // check that the physical address is ok (catch bad physical addresses) + if (req->getPaddr() & ~PAddrImplMask) { + return new MachineCheckFault(); + } + + return checkCacheability(req, true); + +} + +Fault +TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) +{ + mode_type mode = + (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)); + + /** + * Check for alignment faults + */ + if (req->getVaddr() & (req->getSize() - 1)) { + DPRINTF(TLB, "Alignment Fault on %#x, size = %d\n", req->getVaddr(), + req->getSize()); + uint64_t flags = write ? MM_STAT_WR_MASK : 0; + return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags); + } + + if (PcPAL(req->getPC())) { + mode = (req->getFlags() & Request::ALTMODE) ? + (mode_type)ALT_MODE_AM( + tc->readMiscRegNoEffect(IPR_ALT_MODE)) + : mode_kernel; + } + + if (req->getFlags() & Request::PHYSICAL) { + req->setPaddr(req->getVaddr()); + } else { + // verify that this is a good virtual address + if (!validVirtualAddress(req->getVaddr())) { + if (write) { write_acv++; } else { read_acv++; } + uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_BAD_VA_MASK | + MM_STAT_ACV_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + } + + // Check for "superpage" mapping + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { + // only valid in kernel mode + if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) != + mode_kernel) { + if (write) { write_acv++; } else { read_acv++; } + uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | + MM_STAT_ACV_MASK); + + return new DtbAcvFault(req->getVaddr(), req->getFlags(), + flags); + } + + req->setPaddr(req->getVaddr() & PAddrImplMask); + + // sign extend the physical address properly + if (req->getPaddr() & PAddrUncachedBit40) + req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); + else + req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); + } else { + if (write) + write_accesses++; + else + read_accesses++; + + int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); + + // not a physical address: need to look up pte + TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), asn); + + if (!entry) { + // page fault + if (write) { write_misses++; } else { read_misses++; } + uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_DTB_MISS_MASK; + return (req->getFlags() & Request::VPTE) ? + (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), + flags)) : + (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), + flags)); + } + + req->setPaddr((entry->ppn << PageShift) + + VAddr(req->getVaddr()).offset()); + + if (write) { + if (!(entry->xwe & MODE2MASK(mode))) { + // declare the instruction access fault + write_acv++; + uint64_t flags = MM_STAT_WR_MASK | + MM_STAT_ACV_MASK | + (entry->fonw ? MM_STAT_FONW_MASK : 0); + return new DtbPageFault(req->getVaddr(), req->getFlags(), + flags); + } + if (entry->fonw) { + write_acv++; + uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), + flags); + } + } else { + if (!(entry->xre & MODE2MASK(mode))) { + read_acv++; + uint64_t flags = MM_STAT_ACV_MASK | + (entry->fonr ? MM_STAT_FONR_MASK : 0); + return new DtbAcvFault(req->getVaddr(), req->getFlags(), + flags); + } + if (entry->fonr) { + read_acv++; + uint64_t flags = MM_STAT_FONR_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), + flags); + } + } + } + + if (write) + write_hits++; + else + read_hits++; + } + + // check that the physical address is ok (catch bad physical addresses) + if (req->getPaddr() & ~PAddrImplMask) { + return new MachineCheckFault(); + } + + return checkCacheability(req); +} + +TlbEntry & +TLB::index(bool advance) +{ + TlbEntry *entry = &table[nlu]; + + if (advance) + nextnlu(); + + return *entry; +} + +Fault +TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) +{ + if (mode == Execute) + return translateInst(req, tc); + else + return translateData(req, tc, mode == Write); +} + +void +TLB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, Mode mode) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, mode), req, tc, mode); +} + +Fault +TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode) +{ + panic("Not implemented\n"); + return NoFault; +} + +} // namespace AlphaISA + +AlphaISA::TLB * +AlphaTLBParams::create() +{ + return new AlphaISA::TLB(this); +} diff --git a/simulators/gem5/src/arch/alpha/tlb.hh b/simulators/gem5/src/arch/alpha/tlb.hh new file mode 100644 index 00000000..4e56100c --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tlb.hh @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_TLB_HH__ +#define __ARCH_ALPHA_TLB_HH__ + +#include + +#include "arch/alpha/ev5.hh" +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" +#include "arch/alpha/utility.hh" +#include "arch/alpha/vtophys.hh" +#include "base/statistics.hh" +#include "mem/request.hh" +#include "params/AlphaTLB.hh" +#include "sim/fault_fwd.hh" +#include "sim/tlb.hh" + +class ThreadContext; + +namespace AlphaISA { + +struct TlbEntry; + +class TLB : public BaseTLB +{ + protected: + mutable Stats::Scalar fetch_hits; + mutable Stats::Scalar fetch_misses; + mutable Stats::Scalar fetch_acv; + mutable Stats::Formula fetch_accesses; + mutable Stats::Scalar read_hits; + mutable Stats::Scalar read_misses; + mutable Stats::Scalar read_acv; + mutable Stats::Scalar read_accesses; + mutable Stats::Scalar write_hits; + mutable Stats::Scalar write_misses; + mutable Stats::Scalar write_acv; + mutable Stats::Scalar write_accesses; + Stats::Formula data_hits; + Stats::Formula data_misses; + Stats::Formula data_acv; + Stats::Formula data_accesses; + + + typedef std::multimap PageTable; + PageTable lookupTable; // Quick lookup into page table + + TlbEntry *table; // the Page Table + int size; // TLB Size + int nlu; // not last used entry (for replacement) + + void nextnlu() { if (++nlu >= size) nlu = 0; } + TlbEntry *lookup(Addr vpn, uint8_t asn); + + public: + typedef AlphaTLBParams Params; + TLB(const Params *p); + virtual ~TLB(); + + virtual void regStats(); + + int getsize() const { return size; } + + TlbEntry &index(bool advance = true); + void insert(Addr vaddr, TlbEntry &entry); + + void flushAll(); + void flushProcesses(); + void flushAddr(Addr addr, uint8_t asn); + + void + demapPage(Addr vaddr, uint64_t asn) + { + assert(asn < (1 << 8)); + flushAddr(vaddr, asn); + } + + // static helper functions... really EV5 VM traits + static bool + validVirtualAddress(Addr vaddr) + { + // unimplemented bits must be all 0 or all 1 + Addr unimplBits = vaddr & VAddrUnImplMask; + return unimplBits == 0 || unimplBits == VAddrUnImplMask; + } + + static Fault checkCacheability(RequestPtr &req, bool itb = false); + + // Checkpointing + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + // Most recently used page table entries + TlbEntry *EntryCache[3]; + inline void + flushCache() + { + memset(EntryCache, 0, 3 * sizeof(TlbEntry*)); + } + + inline TlbEntry * + updateCache(TlbEntry *entry) { + EntryCache[2] = EntryCache[1]; + EntryCache[1] = EntryCache[0]; + EntryCache[0] = entry; + return entry; + } + + protected: + Fault translateData(RequestPtr req, ThreadContext *tc, bool write); + Fault translateInst(RequestPtr req, ThreadContext *tc); + + public: + Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, Mode mode); + /** + * translateFunctional stub function for future CheckerCPU support + */ + Fault translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode); +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_TLB_HH__ diff --git a/simulators/gem5/src/arch/alpha/tru64/process.cc b/simulators/gem5/src/arch/alpha/tru64/process.cc new file mode 100644 index 00000000..071428d5 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tru64/process.cc @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Ali Saidi + */ + +#include "arch/alpha/tru64/process.hh" +#include "arch/alpha/tru64/tru64.hh" +#include "arch/alpha/isa_traits.hh" +#include "cpu/thread_context.hh" +#include "kern/tru64/tru64.hh" +#include "sim/byteswap.hh" +#include "sim/process.hh" +#include "sim/syscall_emul.hh" + +using namespace std; +using namespace AlphaISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + TypedBufferArg name(process->getSyscallArg(tc, index)); + + strcpy(name->sysname, "OSF1"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "V5.1"); + strcpy(name->version, "732"); + strcpy(name->machine, "alpha"); + + name.copyOut(tc->getMemProxy()); + return 0; +} + +/// Target getsysyinfo() handler. +static SyscallReturn +getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); + unsigned nbytes = process->getSyscallArg(tc, index); + + switch (op) { + + case AlphaTru64::GSI_MAX_CPU: { + TypedBufferArg max_cpu(bufPtr); + *max_cpu = htog((uint32_t)process->numCpus()); + max_cpu.copyOut(tc->getMemProxy()); + return 1; + } + + case AlphaTru64::GSI_CPUS_IN_BOX: { + TypedBufferArg cpus_in_box(bufPtr); + *cpus_in_box = htog((uint32_t)process->numCpus()); + cpus_in_box.copyOut(tc->getMemProxy()); + return 1; + } + + case AlphaTru64::GSI_PHYSMEM: { + TypedBufferArg physmem(bufPtr); + *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB + physmem.copyOut(tc->getMemProxy()); + return 1; + } + + case AlphaTru64::GSI_CPU_INFO: { + TypedBufferArg infop(bufPtr); + + infop->current_cpu = htog(0); + infop->cpus_in_box = htog(process->numCpus()); + infop->cpu_type = htog(57); + infop->ncpus = htog(process->numCpus()); + uint64_t cpumask = (1 << process->numCpus()) - 1; + infop->cpus_present = infop->cpus_running = htog(cpumask); + infop->cpu_binding = htog(0); + infop->cpu_ex_binding = htog(0); + infop->mhz = htog(667); + + infop.copyOut(tc->getMemProxy()); + return 1; + } + + case AlphaTru64::GSI_PROC_TYPE: { + TypedBufferArg proc_type(bufPtr); + *proc_type = htog((uint64_t)11); + proc_type.copyOut(tc->getMemProxy()); + return 1; + } + + case AlphaTru64::GSI_PLATFORM_NAME: { + BufferArg bufArg(bufPtr, nbytes); + strncpy((char *)bufArg.bufferPtr(), + "COMPAQ Professional Workstation XP1000", + nbytes); + bufArg.copyOut(tc->getMemProxy()); + return 1; + } + + case AlphaTru64::GSI_CLK_TCK: { + TypedBufferArg clk_hz(bufPtr); + *clk_hz = htog((uint64_t)1024); + clk_hz.copyOut(tc->getMemProxy()); + return 1; + } + + default: + warn("getsysinfo: unknown op %d\n", op); + break; + } + + return 0; +} + +/// Target setsysyinfo() handler. +static SyscallReturn +setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + + switch (op) { + case AlphaTru64::SSI_IEEE_FP_CONTROL: + warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", + process->getSyscallArg(tc, index)); + break; + + default: + warn("setsysinfo: unknown op %d\n", op); + break; + } + + return 0; +} + +/// Target table() handler. +static SyscallReturn +tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + using namespace std; + + int argIndex = 0; + int id = process->getSyscallArg(tc, argIndex); // table ID + int index = process->getSyscallArg(tc, argIndex); // index into table + Addr bufPtr = process->getSyscallArg(tc, argIndex); + // arg 2 is buffer pointer; type depends on table ID + int nel = process->getSyscallArg(tc, argIndex); // number of elements + int lel = process->getSyscallArg(tc, argIndex); // expected element size + + switch (id) { + case AlphaTru64::TBL_SYSINFO: { + if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) + return -EINVAL; + TypedBufferArg elp(bufPtr); + + const int clk_hz = one_million; + elp->si_user = htog(curTick() / (SimClock::Frequency / clk_hz)); + elp->si_nice = htog(0); + elp->si_sys = htog(0); + elp->si_idle = htog(0); + elp->wait = htog(0); + elp->si_hz = htog(clk_hz); + elp->si_phz = htog(clk_hz); + elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? + elp->si_max_procs = htog(process->numCpus()); + elp.copyOut(tc->getMemProxy()); + return 0; + } + + default: + cerr << "table(): id " << id << " unknown." << endl; + return -EINVAL; + } +} + +SyscallDesc AlphaTru64Process::syscallDescs[] = { + /* 0 */ SyscallDesc("syscall (#0)", AlphaTru64::indirectSyscallFunc, + SyscallDesc::SuppressReturnValue), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("old_open", unimplementedFunc), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("wait4", unimplementedFunc), + /* 8 */ SyscallDesc("old_creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execv", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("fchdir", unimplementedFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", unimplementedFunc), + /* 16 */ SyscallDesc("chown", unimplementedFunc), + /* 17 */ SyscallDesc("obreak", brkFunc), + /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getpid", getpidPseudoFunc), + /* 21 */ SyscallDesc("mount", unimplementedFunc), + /* 22 */ SyscallDesc("unmount", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getuid", getuidPseudoFunc), + /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 28 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 29 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 30 */ SyscallDesc("accept", unimplementedFunc), + /* 31 */ SyscallDesc("getpeername", unimplementedFunc), + /* 32 */ SyscallDesc("getsockname", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("chflags", unimplementedFunc), + /* 35 */ SyscallDesc("fchflags", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("old_stat", unimplementedFunc), + /* 39 */ SyscallDesc("setpgid", unimplementedFunc), + /* 40 */ SyscallDesc("old_lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc), + /* 44 */ SyscallDesc("profil", unimplementedFunc), + /* 45 */ SyscallDesc("open", openFunc), + /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidPseudoFunc), + /* 48 */ SyscallDesc("sigprocmask", ignoreFunc), + /* 49 */ SyscallDesc("getlogin", unimplementedFunc), + /* 50 */ SyscallDesc("setlogin", unimplementedFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("sigpending", unimplementedFunc), + /* 53 */ SyscallDesc("classcntl", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", ioctlFunc), + /* 55 */ SyscallDesc("reboot", unimplementedFunc), + /* 56 */ SyscallDesc("revoke", unimplementedFunc), + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", readlinkFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("old_fstat", unimplementedFunc), + /* 63 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), + /* 65 */ SyscallDesc("mremap", unimplementedFunc), + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("pre_F64_stat", statFunc), + /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc), + /* 69 */ SyscallDesc("sbrk", unimplementedFunc), + /* 70 */ SyscallDesc("sstk", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc), + /* 72 */ SyscallDesc("ovadvise", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", ignoreFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("kmodcall", unimplementedFunc), + /* 78 */ SyscallDesc("mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), + /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setpgrp", unimplementedFunc), + /* 83 */ SyscallDesc("setitimer", unimplementedFunc), + /* 84 */ SyscallDesc("old_wait", unimplementedFunc), + /* 85 */ SyscallDesc("table", tableFunc), + /* 86 */ SyscallDesc("getitimer", unimplementedFunc), + /* 87 */ SyscallDesc("gethostname", gethostnameFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), + /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc), + /* 92 */ SyscallDesc("fcntl", fcntlFunc), + /* 93 */ SyscallDesc("select", unimplementedFunc), + /* 94 */ SyscallDesc("poll", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("old_accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), + /* 101 */ SyscallDesc("old_send", unimplementedFunc), + /* 102 */ SyscallDesc("old_recv", unimplementedFunc), + /* 103 */ SyscallDesc("sigreturn", AlphaTru64::sigreturnFunc, + SyscallDesc::SuppressReturnValue), + /* 104 */ SyscallDesc("bind", unimplementedFunc), + /* 105 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 106 */ SyscallDesc("listen", unimplementedFunc), + /* 107 */ SyscallDesc("plock", unimplementedFunc), + /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc), + /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc), + /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc), + /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 112 */ SyscallDesc("sigstack", ignoreFunc), + /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc), + /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc), + /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc), + /* 117 */ SyscallDesc("getrusage", getrusageFunc), + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", unimplementedFunc), + /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), + /* 127 */ SyscallDesc("setregid", unimplementedFunc), + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", truncateFunc), + /* 130 */ SyscallDesc("ftruncate", ftruncateFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("setgid", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", mkdirFunc), + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("utimes", unimplementedFunc), + /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc), + /* 140 */ SyscallDesc("adjtime", unimplementedFunc), + /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("gethostid", unimplementedFunc), + /* 143 */ SyscallDesc("sethostid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", getrlimitFunc), + /* 145 */ SyscallDesc("setrlimit", ignoreFunc), + /* 146 */ SyscallDesc("old_killpg", unimplementedFunc), + /* 147 */ SyscallDesc("setsid", unimplementedFunc), + /* 148 */ SyscallDesc("quotactl", unimplementedFunc), + /* 149 */ SyscallDesc("oldquota", unimplementedFunc), + /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("pread", unimplementedFunc), + /* 152 */ SyscallDesc("pwrite", unimplementedFunc), + /* 153 */ SyscallDesc("pid_block", unimplementedFunc), + /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc), + /* 155 */ SyscallDesc("signal_urti", unimplementedFunc), + /* 156 */ SyscallDesc("sigaction", ignoreFunc), + /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc), + /* 158 */ SyscallDesc("nfssvc", unimplementedFunc), + /* 159 */ SyscallDesc("getdirentries", AlphaTru64::getdirentriesFunc), + /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc), + /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc), + /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), + /* 163 */ SyscallDesc("async_daemon", unimplementedFunc), + /* 164 */ SyscallDesc("getfh", unimplementedFunc), + /* 165 */ SyscallDesc("getdomainname", unimplementedFunc), + /* 166 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 167 */ SyscallDesc("unknown #167", unimplementedFunc), + /* 168 */ SyscallDesc("unknown #168", unimplementedFunc), + /* 169 */ SyscallDesc("exportfs", unimplementedFunc), + /* 170 */ SyscallDesc("unknown #170", unimplementedFunc), + /* 171 */ SyscallDesc("unknown #171", unimplementedFunc), + /* 172 */ SyscallDesc("unknown #172", unimplementedFunc), + /* 173 */ SyscallDesc("unknown #173", unimplementedFunc), + /* 174 */ SyscallDesc("unknown #174", unimplementedFunc), + /* 175 */ SyscallDesc("unknown #175", unimplementedFunc), + /* 176 */ SyscallDesc("unknown #176", unimplementedFunc), + /* 177 */ SyscallDesc("unknown #177", unimplementedFunc), + /* 178 */ SyscallDesc("unknown #178", unimplementedFunc), + /* 179 */ SyscallDesc("unknown #179", unimplementedFunc), + /* 180 */ SyscallDesc("unknown #180", unimplementedFunc), + /* 181 */ SyscallDesc("alt_plock", unimplementedFunc), + /* 182 */ SyscallDesc("unknown #182", unimplementedFunc), + /* 183 */ SyscallDesc("unknown #183", unimplementedFunc), + /* 184 */ SyscallDesc("getmnt", unimplementedFunc), + /* 185 */ SyscallDesc("unknown #185", unimplementedFunc), + /* 186 */ SyscallDesc("unknown #186", unimplementedFunc), + /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc), + /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc), + /* 189 */ SyscallDesc("unknown #189", unimplementedFunc), + /* 190 */ SyscallDesc("unknown #190", unimplementedFunc), + /* 191 */ SyscallDesc("unknown #191", unimplementedFunc), + /* 192 */ SyscallDesc("unknown #192", unimplementedFunc), + /* 193 */ SyscallDesc("unknown #193", unimplementedFunc), + /* 194 */ SyscallDesc("unknown #194", unimplementedFunc), + /* 195 */ SyscallDesc("unknown #195", unimplementedFunc), + /* 196 */ SyscallDesc("unknown #196", unimplementedFunc), + /* 197 */ SyscallDesc("unknown #197", unimplementedFunc), + /* 198 */ SyscallDesc("unknown #198", unimplementedFunc), + /* 199 */ SyscallDesc("swapon", unimplementedFunc), + /* 200 */ SyscallDesc("msgctl", unimplementedFunc), + /* 201 */ SyscallDesc("msgget", unimplementedFunc), + /* 202 */ SyscallDesc("msgrcv", unimplementedFunc), + /* 203 */ SyscallDesc("msgsnd", unimplementedFunc), + /* 204 */ SyscallDesc("semctl", unimplementedFunc), + /* 205 */ SyscallDesc("semget", unimplementedFunc), + /* 206 */ SyscallDesc("semop", unimplementedFunc), + /* 207 */ SyscallDesc("uname", unameFunc), + /* 208 */ SyscallDesc("lchown", unimplementedFunc), + /* 209 */ SyscallDesc("shmat", unimplementedFunc), + /* 210 */ SyscallDesc("shmctl", unimplementedFunc), + /* 211 */ SyscallDesc("shmdt", unimplementedFunc), + /* 212 */ SyscallDesc("shmget", unimplementedFunc), + /* 213 */ SyscallDesc("mvalid", unimplementedFunc), + /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc), + /* 215 */ SyscallDesc("msleep", unimplementedFunc), + /* 216 */ SyscallDesc("mwakeup", unimplementedFunc), + /* 217 */ SyscallDesc("msync", unimplementedFunc), + /* 218 */ SyscallDesc("signal", unimplementedFunc), + /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc), + /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc), + /* 221 */ SyscallDesc("unknown #221", unimplementedFunc), + /* 222 */ SyscallDesc("security", unimplementedFunc), + /* 223 */ SyscallDesc("kloadcall", unimplementedFunc), + /* 224 */ SyscallDesc("stat", statFunc), + /* 225 */ SyscallDesc("lstat", lstatFunc), + /* 226 */ SyscallDesc("fstat", fstatFunc), + /* 227 */ SyscallDesc("statfs", statfsFunc), + /* 228 */ SyscallDesc("fstatfs", fstatfsFunc), + /* 229 */ SyscallDesc("getfsstat", unimplementedFunc), + /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc), + /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc), + /* 232 */ SyscallDesc("unknown #232", unimplementedFunc), + /* 233 */ SyscallDesc("getpgid", unimplementedFunc), + /* 234 */ SyscallDesc("getsid", unimplementedFunc), + /* 235 */ SyscallDesc("sigaltstack", ignoreFunc), + /* 236 */ SyscallDesc("waitid", unimplementedFunc), + /* 237 */ SyscallDesc("priocntlset", unimplementedFunc), + /* 238 */ SyscallDesc("sigsendset", unimplementedFunc), + /* 239 */ SyscallDesc("set_speculative", unimplementedFunc), + /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc), + /* 241 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 242 */ SyscallDesc("uadmin", unimplementedFunc), + /* 243 */ SyscallDesc("fuser", unimplementedFunc), + /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc), + /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc), + /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc), + /* 247 */ SyscallDesc("pathconf", unimplementedFunc), + /* 248 */ SyscallDesc("fpathconf", unimplementedFunc), + /* 249 */ SyscallDesc("sync2", unimplementedFunc), + /* 250 */ SyscallDesc("uswitch", unimplementedFunc), + /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc), + /* 252 */ SyscallDesc("audcntl", unimplementedFunc), + /* 253 */ SyscallDesc("audgen", unimplementedFunc), + /* 254 */ SyscallDesc("sysfs", unimplementedFunc), + /* 255 */ SyscallDesc("subsys_info", unimplementedFunc), + /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc), + /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc), + /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 259 */ SyscallDesc("swapctl", unimplementedFunc), + /* 260 */ SyscallDesc("memcntl", unimplementedFunc), + /* 261 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 262 */ SyscallDesc("oflock", unimplementedFunc), + /* 263 */ SyscallDesc("F64_readv", unimplementedFunc), + /* 264 */ SyscallDesc("F64_writev", unimplementedFunc), + /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc), + /* 266 */ SyscallDesc("sendfile", unimplementedFunc), +}; + +SyscallDesc AlphaTru64Process::machSyscallDescs[] = { + /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc), + /* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc), + /* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc), + /* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc), + /* 5 */ SyscallDesc("m5_cond_broadcast", + AlphaTru64::m5_cond_broadcastFunc), + /* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc), + /* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc), + /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 10 */ SyscallDesc("task_self", unimplementedFunc), + /* 11 */ SyscallDesc("thread_reply", unimplementedFunc), + /* 12 */ SyscallDesc("task_notify", unimplementedFunc), + /* 13 */ SyscallDesc("thread_self", unimplementedFunc), + /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc), + /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc), + /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc), + /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 24 */ SyscallDesc("nxm_block", AlphaTru64::nxm_blockFunc), + /* 25 */ SyscallDesc("nxm_unblock", AlphaTru64::nxm_unblockFunc), + /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc), + /* 30 */ SyscallDesc("lw_wire", unimplementedFunc), + /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc), + /* 32 */ SyscallDesc("nxm_thread_create", + AlphaTru64::nxm_thread_createFunc), + /* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc), + /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 35 */ SyscallDesc("nxm_idle", AlphaTru64::nxm_idleFunc), + /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc), + /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc), + /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc), + /* 39 */ SyscallDesc("nxm_thread_block", AlphaTru64::nxm_thread_blockFunc), + /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc), + /* 41 */ SyscallDesc("init_process", unimplementedFunc), + /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc), + /* 43 */ SyscallDesc("map_fd", unimplementedFunc), + /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc), + /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc), + /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc), + /* 47 */ SyscallDesc("stack_create", AlphaTru64::stack_createFunc), + /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc), + /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc), + /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc), + /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc), + /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc), + /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 55 */ SyscallDesc("host_self", unimplementedFunc), + /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc), + /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 59 */ SyscallDesc("swtch_pri", AlphaTru64::swtch_priFunc), + /* 60 */ SyscallDesc("swtch", unimplementedFunc), + /* 61 */ SyscallDesc("thread_switch", unimplementedFunc), + /* 62 */ SyscallDesc("semop_fast", unimplementedFunc), + /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc), + /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc), + /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc), + /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc), + /* 67 */ SyscallDesc("nxm_swtch_pri", AlphaTru64::swtch_priFunc), + /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc), + /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc), + /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc), + /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc), + /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc), + /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc), + /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc), + /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc), + /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc), + /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc), + /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc), + /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc), + /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc), + /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc), + /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc) +}; + +SyscallDesc* +AlphaTru64Process::getDesc(int callnum) +{ + if (callnum < -Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs) + return NULL; + + if (callnum < 0) + return &machSyscallDescs[-callnum]; + else + return &syscallDescs[callnum]; +} + +AlphaTru64Process::AlphaTru64Process(LiveProcessParams *params, + ObjectFile *objFile) + : AlphaLiveProcess(params, objFile), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)), + Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc)) +{ +} diff --git a/simulators/gem5/src/arch/alpha/tru64/process.hh b/simulators/gem5/src/arch/alpha/tru64/process.hh new file mode 100644 index 00000000..6d7a7655 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tru64/process.hh @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_TRU64_PROCESS_HH__ +#define __ARCH_ALPHA_TRU64_PROCESS_HH__ + +#include "arch/alpha/process.hh" + +namespace AlphaISA { + +/// A process with emulated Alpha Tru64 syscalls. +class AlphaTru64Process : public AlphaLiveProcess +{ + public: + /// Constructor. + AlphaTru64Process(LiveProcessParams * params, + ObjectFile *objFile); + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + /// Array of mach syscall descriptors, indexed by call number. + static SyscallDesc machSyscallDescs[]; + + const int Num_Syscall_Descs; + const int Num_Mach_Syscall_Descs; + + virtual SyscallDesc *getDesc(int callnum); +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_TRU64_PROCESS_HH__ diff --git a/simulators/gem5/src/arch/alpha/tru64/system.cc b/simulators/gem5/src/arch/alpha/tru64/system.cc new file mode 100644 index 00000000..cb4b8dd5 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tru64/system.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Lisa Hsu + */ + +#include "arch/alpha/tru64/system.hh" +#include "arch/isa_traits.hh" +#include "arch/vtophys.hh" +#include "base/loader/symtab.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "kern/tru64/tru64_events.hh" +#include "kern/system_events.hh" +#include "mem/fs_translating_port_proxy.hh" + +using namespace std; + +Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p) + : AlphaSystem(p) +{ + Addr addr = 0; + if (kernelSymtab->findAddress("enable_async_printf", addr)) { + virtProxy.write(addr, (uint32_t)0); + } + +#ifdef DEBUG + kernelPanicEvent = addKernelFuncEvent("panic"); + if (!kernelPanicEvent) + panic("could not find kernel symbol \'panic\'"); +#endif + + badaddrEvent = addKernelFuncEvent("badaddr"); + if (!badaddrEvent) + panic("could not find kernel symbol \'badaddr\'"); + + skipPowerStateEvent = + addKernelFuncEvent("tl_v48_capture_power_state"); + skipScavengeBootEvent = + addKernelFuncEvent("pmap_scavenge_boot"); + +#if TRACING_ON + printfEvent = addKernelFuncEvent("printf"); + debugPrintfEvent = addKernelFuncEvent("m5printf"); + debugPrintfrEvent = addKernelFuncEvent("m5printfr"); + dumpMbufEvent = addKernelFuncEvent("m5_dump_mbuf"); +#endif +} + +Tru64AlphaSystem::~Tru64AlphaSystem() +{ +#ifdef DEBUG + delete kernelPanicEvent; +#endif + delete badaddrEvent; + delete skipPowerStateEvent; + delete skipScavengeBootEvent; +#if TRACING_ON + delete printfEvent; + delete debugPrintfEvent; + delete debugPrintfrEvent; + delete dumpMbufEvent; +#endif +} + +Tru64AlphaSystem * +Tru64AlphaSystemParams::create() +{ + return new Tru64AlphaSystem(this); +} diff --git a/simulators/gem5/src/arch/alpha/tru64/system.hh b/simulators/gem5/src/arch/alpha/tru64/system.hh new file mode 100644 index 00000000..815a3421 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tru64/system.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Lisa Hsu + */ + +#ifndef __ARCH_ALPHA_TRU64_SYSTEM_HH__ +#define __ARCH_ALPHA_TRU64_SYSTEM_HH__ + +#include "arch/alpha/system.hh" +#include "arch/isa_traits.hh" +#include "params/Tru64AlphaSystem.hh" +#include "sim/system.hh" + +class ThreadContext; + +class BreakPCEvent; +class BadAddrEvent; +class SkipFuncEvent; +class PrintfEvent; +class DebugPrintfEvent; +class DebugPrintfrEvent; +class DumpMbufEvent; +class AlphaArguments; + +class Tru64AlphaSystem : public AlphaSystem +{ + private: +#ifdef DEBUG + /** Event to halt the simulator if the kernel calls panic() */ + BreakPCEvent *kernelPanicEvent; +#endif + + BadAddrEvent *badaddrEvent; + SkipFuncEvent *skipPowerStateEvent; + SkipFuncEvent *skipScavengeBootEvent; + PrintfEvent *printfEvent; + DebugPrintfEvent *debugPrintfEvent; + DebugPrintfrEvent *debugPrintfrEvent; + DumpMbufEvent *dumpMbufEvent; + + public: + typedef Tru64AlphaSystemParams Params; + Tru64AlphaSystem(Params *p); + ~Tru64AlphaSystem(); + + static void Printf(AlphaArguments args); + static void DumpMbuf(AlphaArguments args); +}; + +#endif // __ARCH_ALPHA_TRU64_SYSTEM_HH__ diff --git a/simulators/gem5/src/arch/alpha/tru64/tru64.cc b/simulators/gem5/src/arch/alpha/tru64/tru64.cc new file mode 100644 index 00000000..c72e975f --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tru64/tru64.cc @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#include "arch/alpha/tru64/tru64.hh" + +// open(2) flags translation table +OpenFlagTransTable AlphaTru64::openFlagTable[] = { +#ifdef _MSC_VER + { AlphaTru64::TGT_O_RDONLY, _O_RDONLY }, + { AlphaTru64::TGT_O_WRONLY, _O_WRONLY }, + { AlphaTru64::TGT_O_RDWR, _O_RDWR }, + { AlphaTru64::TGT_O_APPEND, _O_APPEND }, + { AlphaTru64::TGT_O_CREAT, _O_CREAT }, + { AlphaTru64::TGT_O_TRUNC, _O_TRUNC }, + { AlphaTru64::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { AlphaTru64::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { AlphaTru64::TGT_O_RDONLY, O_RDONLY }, + { AlphaTru64::TGT_O_WRONLY, O_WRONLY }, + { AlphaTru64::TGT_O_RDWR, O_RDWR }, + { AlphaTru64::TGT_O_APPEND, O_APPEND }, + { AlphaTru64::TGT_O_CREAT, O_CREAT }, + { AlphaTru64::TGT_O_TRUNC, O_TRUNC }, + { AlphaTru64::TGT_O_EXCL, O_EXCL }, + { AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK }, + { AlphaTru64::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { AlphaTru64::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int AlphaTru64::NUM_OPEN_FLAGS = + (sizeof(AlphaTru64::openFlagTable)/sizeof(AlphaTru64::openFlagTable[0])); + + + diff --git a/simulators/gem5/src/arch/alpha/tru64/tru64.hh b/simulators/gem5/src/arch/alpha/tru64/tru64.hh new file mode 100644 index 00000000..f0cad828 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/tru64/tru64.hh @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ALPHA_ALPHA_TRU64_TRU64_HH__ +#define __ALPHA_ALPHA_TRU64_TRU64_HH__ + +#include "kern/tru64/tru64.hh" + +class AlphaTru64 : public Tru64 +{ + public: + /// This table maps the target open() flags to the corresponding + /// host open() flags. + static OpenFlagTransTable openFlagTable[]; + + /// Number of entries in openFlagTable[]. + static const int NUM_OPEN_FLAGS; + + //@{ + /// open(2) flag values. + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x10; + static const unsigned TGT_MAP_FIXED = 0x100; + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + //@} + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_THREAD = 1; + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + //@} + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + //@{ + /// ioctl() command codes. + static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCSETP_ = 0x80067409; + static const unsigned TIOCSETN_ = 0x8006740a; + static const unsigned TIOCSETC_ = 0x80067411; + static const unsigned TIOCGETC_ = 0x40067412; + static const unsigned FIONREAD_ = 0x4004667f; + static const unsigned TIOCISATTY_ = 0x2000745e; + static const unsigned TIOCGETS_ = 0x402c7413; + static const unsigned TIOCGETA_ = 0x40127417; + static const unsigned TCSETAW_ = 0x80147419; + //@} + + //@{ + /// For table(). + static const int TBL_SYSINFO = 12; + //@} + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NOFILE = 6, + TGT_RLIMIT_AS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; +}; + +#endif // __ALPHA_ALPHA_TRU64_TRU64_HH__ diff --git a/simulators/gem5/src/arch/alpha/types.hh b/simulators/gem5/src/arch/alpha/types.hh new file mode 100644 index 00000000..b1411d46 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/types.hh @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_TYPES_HH__ +#define __ARCH_ALPHA_TYPES_HH__ + +#include "arch/generic/types.hh" +#include "base/types.hh" + +namespace AlphaISA { + +typedef uint32_t MachInst; +typedef uint64_t ExtMachInst; + +typedef GenericISA::SimplePCState PCState; + +typedef uint64_t LargestRead; + +enum annotes +{ + ANNOTE_NONE = 0, + // An impossible number for instruction annotations + ITOUCH_ANNOTE = 0xffffffff +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_TYPES_HH__ diff --git a/simulators/gem5/src/arch/alpha/utility.cc b/simulators/gem5/src/arch/alpha/utility.cc new file mode 100644 index 00000000..32fc0b14 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/utility.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +#include "arch/alpha/utility.hh" +#include "arch/alpha/vtophys.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "sim/full_system.hh" + +namespace AlphaISA { + +uint64_t +getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) +{ + if (!FullSystem) { + panic("getArgument() is Full system only\n"); + M5_DUMMY_RETURN; + } + + const int NumArgumentRegs = 6; + if (number < NumArgumentRegs) { + if (fp) + return tc->readFloatRegBits(16 + number); + else + return tc->readIntReg(16 + number); + } else { + Addr sp = tc->readIntReg(StackPointerReg); + FSTranslatingPortProxy &vp = tc->getVirtProxy(); + uint64_t arg = vp.read(sp + + (number-NumArgumentRegs) * + sizeof(uint64_t)); + return arg; + } +} + +void +copyRegs(ThreadContext *src, ThreadContext *dest) +{ + // First loop through the integer registers. + for (int i = 0; i < NumIntRegs; ++i) + dest->setIntReg(i, src->readIntReg(i)); + + // Then loop through the floating point registers. + for (int i = 0; i < NumFloatRegs; ++i) + dest->setFloatRegBits(i, src->readFloatRegBits(i)); + + // Copy misc. registers + copyMiscRegs(src, dest); + + // Lastly copy PC/NPC + dest->pcState(src->pcState()); +} + +void +copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + dest->setMiscRegNoEffect(MISCREG_FPCR, + src->readMiscRegNoEffect(MISCREG_FPCR)); + dest->setMiscRegNoEffect(MISCREG_UNIQ, + src->readMiscRegNoEffect(MISCREG_UNIQ)); + dest->setMiscRegNoEffect(MISCREG_LOCKFLAG, + src->readMiscRegNoEffect(MISCREG_LOCKFLAG)); + dest->setMiscRegNoEffect(MISCREG_LOCKADDR, + src->readMiscRegNoEffect(MISCREG_LOCKADDR)); + + copyIprs(src, dest); +} + +void +skipFunction(ThreadContext *tc) +{ + TheISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(ReturnAddressReg)); + tc->pcState(newPC); +} + + +} // namespace AlphaISA + diff --git a/simulators/gem5/src/arch/alpha/utility.hh b/simulators/gem5/src/arch/alpha/utility.hh new file mode 100644 index 00000000..a9b5c4cb --- /dev/null +++ b/simulators/gem5/src/arch/alpha/utility.hh @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_UTILITY_HH__ +#define __ARCH_ALPHA_UTILITY_HH__ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/registers.hh" +#include "arch/alpha/types.hh" +#include "base/misc.hh" +#include "cpu/static_inst.hh" +#include "cpu/thread_context.hh" +#include "arch/alpha/ev5.hh" + +namespace AlphaISA { + +inline PCState +buildRetPC(const PCState &curPC, const PCState &callPC) +{ + PCState retPC = callPC; + retPC.advance(); + return retPC; +} + +uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); + +inline bool +inUserMode(ThreadContext *tc) +{ + return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; +} + +/** + * Function to insure ISA semantics about 0 registers. + * @param tc The thread context. + */ +template +void zeroRegisters(TC *tc); + +// Alpha IPR register accessors +inline bool PcPAL(Addr addr) { return addr & 0x3; } +inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); } + +//////////////////////////////////////////////////////////////////////// +// +// Translation stuff +// + +inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; } + +// User Virtual +inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; } + +// Kernel Direct Mapped +inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; } +inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; } + +// Kernel Virtual +inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; } + +inline Addr +TruncPage(Addr addr) +{ return addr & ~(PageBytes - 1); } + +inline Addr +RoundPage(Addr addr) +{ return (addr + PageBytes - 1) & ~(PageBytes - 1); } + +void initIPRs(ThreadContext *tc, int cpuId); +void initCPU(ThreadContext *tc, int cpuId); + +void copyRegs(ThreadContext *src, ThreadContext *dest); + +void copyMiscRegs(ThreadContext *src, ThreadContext *dest); + +void skipFunction(ThreadContext *tc); + +inline void +advancePC(PCState &pc, const StaticInstPtr inst) +{ + pc.advance(); +} + +inline uint64_t +getExecutingAsid(ThreadContext *tc) +{ + return DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); +} + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_UTILITY_HH__ diff --git a/simulators/gem5/src/arch/alpha/vtophys.cc b/simulators/gem5/src/arch/alpha/vtophys.cc new file mode 100644 index 00000000..8ca23fce --- /dev/null +++ b/simulators/gem5/src/arch/alpha/vtophys.cc @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + * Ali Saidi + */ + +#include + +#include "arch/alpha/ev5.hh" +#include "arch/alpha/vtophys.hh" +#include "base/chunk_generator.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/VtoPhys.hh" +#include "mem/port_proxy.hh" + +using namespace std; + +namespace AlphaISA { + +PageTableEntry +kernel_pte_lookup(PortProxy &mem, Addr ptbr, VAddr vaddr) +{ + Addr level1_pte = ptbr + vaddr.level1(); + PageTableEntry level1 = mem.read(level1_pte); + if (!level1.valid()) { + DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); + return 0; + } + + Addr level2_pte = level1.paddr() + vaddr.level2(); + PageTableEntry level2 = mem.read(level2_pte); + if (!level2.valid()) { + DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); + return 0; + } + + Addr level3_pte = level2.paddr() + vaddr.level3(); + PageTableEntry level3 = mem.read(level3_pte); + if (!level3.valid()) { + DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); + return 0; + } + return level3; +} + +Addr +vtophys(Addr vaddr) +{ + Addr paddr = 0; + if (IsUSeg(vaddr)) + DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); + else if (IsK0Seg(vaddr)) + paddr = K0Seg2Phys(vaddr); + else + panic("vtophys: ptbr is not set on virtual lookup"); + + DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); + + return paddr; +} + +Addr +vtophys(ThreadContext *tc, Addr addr) +{ + VAddr vaddr = addr; + Addr ptbr = tc->readMiscRegNoEffect(IPR_PALtemp20); + Addr paddr = 0; + //@todo Andrew couldn't remember why he commented some of this code + //so I put it back in. Perhaps something to do with gdb debugging? + if (PcPAL(vaddr) && (vaddr < PalMax)) { + paddr = vaddr & ~ULL(1); + } else { + if (IsK0Seg(vaddr)) { + paddr = K0Seg2Phys(vaddr); + } else if (!ptbr) { + paddr = vaddr; + } else { + PageTableEntry pte = + kernel_pte_lookup(tc->getPhysProxy(), ptbr, vaddr); + if (pte.valid()) + paddr = pte.paddr() | vaddr.offset(); + } + } + + + DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); + + return paddr; +} + +} // namespace AlphaISA diff --git a/simulators/gem5/src/arch/alpha/vtophys.hh b/simulators/gem5/src/arch/alpha/vtophys.hh new file mode 100644 index 00000000..8613e8e7 --- /dev/null +++ b/simulators/gem5/src/arch/alpha/vtophys.hh @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_VTOPHYS_H__ +#define __ARCH_ALPHA_VTOPHYS_H__ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" +#include "arch/alpha/utility.hh" + +class ThreadContext; +class PortProxy; + +namespace AlphaISA { + +PageTableEntry kernel_pte_lookup(PortProxy &mem, Addr ptbr, + VAddr vaddr); + +Addr vtophys(Addr vaddr); +Addr vtophys(ThreadContext *tc, Addr vaddr); + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_VTOPHYS_H__ + diff --git a/simulators/gem5/src/arch/arm/ArmInterrupts.py b/simulators/gem5/src/arch/arm/ArmInterrupts.py new file mode 100644 index 00000000..f21d49e9 --- /dev/null +++ b/simulators/gem5/src/arch/arm/ArmInterrupts.py @@ -0,0 +1,33 @@ +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +from m5.SimObject import SimObject + +class ArmInterrupts(SimObject): + type = 'ArmInterrupts' + cxx_class = 'ArmISA::Interrupts' diff --git a/simulators/gem5/src/arch/arm/ArmNativeTrace.py b/simulators/gem5/src/arch/arm/ArmNativeTrace.py new file mode 100644 index 00000000..0a76913e --- /dev/null +++ b/simulators/gem5/src/arch/arm/ArmNativeTrace.py @@ -0,0 +1,37 @@ +# Copyright (c) 2009 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject +from m5.params import * +from NativeTrace import NativeTrace + +class ArmNativeTrace(NativeTrace): + type = 'ArmNativeTrace' + cxx_class = 'Trace::ArmNativeTrace' + stop_on_pc_error = Param.Bool(True, + "Stop M5 if it and statetrace's pcs are different") diff --git a/simulators/gem5/src/arch/arm/ArmSystem.py b/simulators/gem5/src/arch/arm/ArmSystem.py new file mode 100644 index 00000000..54bf99e9 --- /dev/null +++ b/simulators/gem5/src/arch/arm/ArmSystem.py @@ -0,0 +1,69 @@ +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +from m5.params import * + +from System import System + +class ArmMachineType(Enum): + map = {'RealView_EB' : 827, + 'RealView_PBX' : 1901, + 'VExpress_ELT' : 2272, + 'VExpress_CA9' : 2272, + 'VExpress_EMM' : 2272} + +class ArmSystem(System): + type = 'ArmSystem' + load_addr_mask = 0xffffffff + # 0x35 Implementor is '5' from "M5" + # 0x0 Variant + # 0xf Architecture from CPUID scheme + # 0xc00 Primary part number ("c" or higher implies ARM v7) + # 0x0 Revision + midr_regval = Param.UInt32(0x350fc000, "MIDR value") + multi_proc = Param.Bool(True, "Multiprocessor system?") + boot_loader = Param.String("", "File that contains the boot loader code if any") + gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface") + flags_addr = Param.Addr(0, "Address of the flags register for MP booting") + +class LinuxArmSystem(ArmSystem): + type = 'LinuxArmSystem' + load_addr_mask = 0x0fffffff + machine_type = Param.ArmMachineType('RealView_PBX', + "Machine id from http://www.arm.linux.org.uk/developer/machines/") + atags_addr = Param.Addr(0x100, "Address where default atags structure should be written") + early_kernel_symbols = Param.Bool(False, "enable early kernel symbol tables before MMU") diff --git a/simulators/gem5/src/arch/arm/ArmTLB.py b/simulators/gem5/src/arch/arm/ArmTLB.py new file mode 100644 index 00000000..8599fa75 --- /dev/null +++ b/simulators/gem5/src/arch/arm/ArmTLB.py @@ -0,0 +1,58 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +from m5.SimObject import SimObject +from m5.params import * +from m5.proxy import * +from MemObject import MemObject + +class ArmTableWalker(MemObject): + type = 'ArmTableWalker' + cxx_class = 'ArmISA::TableWalker' + port = MasterPort("Port for TableWalker to do walk the translation with") + sys = Param.System(Parent.any, "system object parameter") + min_backoff = Param.Tick(0, "Minimum backoff delay after failed send") + max_backoff = Param.Tick(100000, "Minimum backoff delay after failed send") + + +class ArmTLB(SimObject): + type = 'ArmTLB' + cxx_class = 'ArmISA::TLB' + size = Param.Int(64, "TLB size") + walker = Param.ArmTableWalker(ArmTableWalker(), "HW Table walker") diff --git a/simulators/gem5/src/arch/arm/SConscript b/simulators/gem5/src/arch/arm/SConscript new file mode 100644 index 00000000..44b6286a --- /dev/null +++ b/simulators/gem5/src/arch/arm/SConscript @@ -0,0 +1,90 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2007-2008 The Florida State University +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Stephen Hines +# Ali Saidi + +Import('*') + +if env['TARGET_ISA'] == 'arm': +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 + Dir('isa/formats') + Source('decoder.cc') + Source('faults.cc') + Source('insts/macromem.cc') + Source('insts/mem.cc') + Source('insts/misc.cc') + Source('insts/pred_inst.cc') + Source('insts/static_inst.cc') + Source('insts/vfp.cc') + Source('interrupts.cc') + Source('isa.cc') + Source('linux/linux.cc') + Source('linux/process.cc') + Source('linux/system.cc') + Source('miscregs.cc') + Source('nativetrace.cc') + Source('process.cc') + Source('remote_gdb.cc') + Source('stacktrace.cc') + Source('system.cc') + Source('table_walker.cc') + Source('tlb.cc') + Source('utility.cc') + Source('vtophys.cc') + + SimObject('ArmInterrupts.py') + SimObject('ArmNativeTrace.py') + SimObject('ArmSystem.py') + SimObject('ArmTLB.py') + + DebugFlag('Arm') + DebugFlag('Decoder', "Instructions returned by the predecoder") + DebugFlag('Faults', "Trace Exceptions, interrupts, svc/swi") + DebugFlag('TLBVerbose') + + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) + diff --git a/simulators/gem5/src/arch/arm/SConsopts b/simulators/gem5/src/arch/arm/SConsopts new file mode 100644 index 00000000..fd951692 --- /dev/null +++ b/simulators/gem5/src/arch/arm/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2007-2008 The Florida State University +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Stephen Hines + +Import('*') + +all_isa_list.append('arm') diff --git a/simulators/gem5/src/arch/arm/decoder.cc b/simulators/gem5/src/arch/arm/decoder.cc new file mode 100644 index 00000000..4001f759 --- /dev/null +++ b/simulators/gem5/src/arch/arm/decoder.cc @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012 Google + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/arm/decoder.hh" +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/Decoder.hh" + +namespace ArmISA +{ + +GenericISA::BasicDecodeCache Decoder::defaultCache; + +void +Decoder::process() +{ + // emi is typically ready, with some caveats below... + instDone = true; + + if (!emi.thumb) { + emi.instBits = data; + emi.sevenAndFour = bits(data, 7) && bits(data, 4); + emi.isMisc = (bits(data, 24, 23) == 0x2 && + bits(data, 20) == 0); + consumeBytes(4); + DPRINTF(Decoder, "Arm inst: %#x.\n", (uint64_t)emi); + } else { + uint16_t word = (data >> (offset * 8)); + if (bigThumb) { + // A 32 bit thumb inst is half collected. + emi.instBits = emi.instBits | word; + bigThumb = false; + consumeBytes(2); + DPRINTF(Decoder, "Second half of 32 bit Thumb: %#x.\n", + emi.instBits); + } else { + uint16_t highBits = word & 0xF800; + if (highBits == 0xE800 || highBits == 0xF000 || + highBits == 0xF800) { + // The start of a 32 bit thumb inst. + emi.bigThumb = 1; + if (offset == 0) { + // We've got the whole thing. + emi.instBits = (data >> 16) | (data << 16); + DPRINTF(Decoder, "All of 32 bit Thumb: %#x.\n", + emi.instBits); + consumeBytes(4); + } else { + // We only have the first half word. + DPRINTF(Decoder, + "First half of 32 bit Thumb.\n"); + emi.instBits = (uint32_t)word << 16; + bigThumb = true; + consumeBytes(2); + // emi not ready yet. + instDone = false; + } + } else { + // A 16 bit thumb inst. + consumeBytes(2); + emi.instBits = word; + // Set the condition code field artificially. + emi.condCode = COND_UC; + DPRINTF(Decoder, "16 bit Thumb: %#x.\n", + emi.instBits); + if (bits(word, 15, 8) == 0xbf && + bits(word, 3, 0) != 0x0) { + foundIt = true; + itBits = bits(word, 7, 0); + DPRINTF(Decoder, + "IT detected, cond = %#x, mask = %#x\n", + itBits.cond, itBits.mask); + } + } + } + } +} + +//Use this to give data to the decoder. This should be used +//when there is control flow. +void +Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) +{ + data = inst; + offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; + emi.thumb = pc.thumb(); + FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR); + emi.fpscrLen = fpscr.len; + emi.fpscrStride = fpscr.stride; + + outOfBytes = false; + process(); +} + +} diff --git a/simulators/gem5/src/arch/arm/decoder.hh b/simulators/gem5/src/arch/arm/decoder.hh new file mode 100644 index 00000000..a5f2c88a --- /dev/null +++ b/simulators/gem5/src/arch/arm/decoder.hh @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2012 Google + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ARM_DECODER_HH__ +#define __ARCH_ARM_DECODER_HH__ + +#include + +#include "arch/arm/miscregs.hh" +#include "arch/arm/types.hh" +#include "arch/generic/decode_cache.hh" +#include "base/types.hh" +#include "cpu/static_inst.hh" + +class ThreadContext; + +namespace ArmISA +{ + +class Decoder +{ + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + MachInst data; + bool bigThumb; + bool instDone; + bool outOfBytes; + int offset; + bool foundIt; + ITSTATE itBits; + + public: + void reset() + { + bigThumb = false; + offset = 0; + emi = 0; + instDone = false; + outOfBytes = true; + foundIt = false; + } + + Decoder(ThreadContext * _tc) : tc(_tc), data(0) + { + reset(); + } + + ThreadContext * getTC() + { + return tc; + } + + void + setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process(); + + //Use this to give data to the decoder. This should be used + //when there is control flow. + void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst); + + //Use this to give data to the decoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + inline void consumeBytes(int numBytes) + { + offset += numBytes; + assert(offset <= sizeof(MachInst)); + if (offset == sizeof(MachInst)) + outOfBytes = true; + } + + bool needMoreBytes() const + { + return outOfBytes; + } + + bool instReady() const + { + return instDone; + } + + int getInstSize() const + { + return (!emi.thumb || emi.bigThumb) ? 4 : 2; + } + + protected: + /// A cache of decoded instruction objects. + static GenericISA::BasicDecodeCache defaultCache; + + public: + StaticInstPtr decodeInst(ExtMachInst mach_inst); + + /// Decode a machine instruction. + /// @param mach_inst The binary instruction to decode. + /// @retval A pointer to the corresponding StaticInst object. + StaticInstPtr + decode(ExtMachInst mach_inst, Addr addr) + { + return defaultCache.decode(this, mach_inst, addr); + } + + StaticInstPtr + decode(ArmISA::PCState &nextPC) + { + if (!instDone) + return NULL; + + assert(instDone); + ExtMachInst thisEmi = emi; + nextPC.npc(nextPC.pc() + getInstSize()); + if (foundIt) + nextPC.nextItstate(itBits); + thisEmi.itstate = nextPC.itstate(); + nextPC.size(getInstSize()); + emi = 0; + instDone = false; + foundIt = false; + return decode(thisEmi, nextPC.instAddr()); + } +}; + +} // namespace ArmISA + +#endif // __ARCH_ARM_DECODER_HH__ diff --git a/simulators/gem5/src/arch/arm/faults.cc b/simulators/gem5/src/arch/arm/faults.cc new file mode 100644 index 00000000..061392f5 --- /dev/null +++ b/simulators/gem5/src/arch/arm/faults.cc @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Gabe Black + */ + +#include "arch/arm/faults.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "debug/Faults.hh" +#include "sim/full_system.hh" + +namespace ArmISA +{ + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"reset", 0x00, MODE_SVC, 0, 0, true, true}; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false}; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false}; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false}; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false}; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true}; + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values + +template<> ArmFault::FaultVals ArmFaultVals::vals = + {"ArmSev Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values +Addr +ArmFault::getVector(ThreadContext *tc) +{ + // ARM ARM B1-3 + + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + + // panic if SCTLR.VE because I have no idea what to do with vectored + // interrupts + assert(!sctlr.ve); + + if (!sctlr.v) + return offset(); + return offset() + HighVecs; + +} + +void +ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + // ARM ARM B1.6.3 + FaultBase::invoke(tc); + if (!FullSystem) + return; + countStat()++; + + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR); + saved_cpsr.nz = tc->readIntReg(INTREG_CONDCODES_NZ); + saved_cpsr.c = tc->readIntReg(INTREG_CONDCODES_C); + saved_cpsr.v = tc->readIntReg(INTREG_CONDCODES_V); + saved_cpsr.ge = tc->readIntReg(INTREG_CONDCODES_GE); + + Addr curPc M5_VAR_USED = tc->pcState().pc(); + ITSTATE it = tc->pcState().itstate(); + saved_cpsr.it2 = it.top6; + saved_cpsr.it1 = it.bottom2; + + cpsr.mode = nextMode(); + cpsr.it1 = cpsr.it2 = 0; + cpsr.j = 0; + + cpsr.t = sctlr.te; + cpsr.a = cpsr.a | abortDisable(); + cpsr.f = cpsr.f | fiqDisable(); + cpsr.i = 1; + cpsr.e = sctlr.ee; + tc->setMiscReg(MISCREG_CPSR, cpsr); + // Make sure mailbox sets to one always + tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); + tc->setIntReg(INTREG_LR, curPc + + (saved_cpsr.t ? thumbPcOffset() : armPcOffset())); + + switch (nextMode()) { + case MODE_FIQ: + tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr); + break; + case MODE_IRQ: + tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr); + break; + case MODE_SVC: + tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr); + break; + case MODE_UNDEFINED: + tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr); + break; + case MODE_ABORT: + tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr); + break; + default: + panic("unknown Mode\n"); + } + + Addr newPc = getVector(tc); + DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n", + name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc); + PCState pc(newPc); + pc.thumb(cpsr.t); + pc.nextThumb(pc.thumb()); + pc.jazelle(cpsr.j); + pc.nextJazelle(pc.jazelle()); + tc->pcState(pc); +} + +void +Reset::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + tc->getCpuPtr()->clearInterrupts(); + tc->clearArchRegs(); + } + ArmFault::invoke(tc, inst); +} + +void +UndefinedInstruction::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + ArmFault::invoke(tc, inst); + return; + } + + // If the mnemonic isn't defined this has to be an unknown instruction. + assert(unknown || mnemonic != NULL); + if (disabled) { + panic("Attempted to execute disabled instruction " + "'%s' (inst 0x%08x)", mnemonic, machInst); + } else if (unknown) { + panic("Attempted to execute unknown instruction (inst 0x%08x)", + machInst); + } else { + panic("Attempted to execute unimplemented instruction " + "'%s' (inst 0x%08x)", mnemonic, machInst); + } +} + +void +SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + if (FullSystem) { + ArmFault::invoke(tc, inst); + return; + } + + // As of now, there isn't a 32 bit thumb version of this instruction. + assert(!machInst.bigThumb); + uint32_t callNum; + callNum = tc->readIntReg(INTREG_R7); + tc->syscall(callNum); + + // Advance the PC since that won't happen automatically. + PCState pc = tc->pcState(); + assert(inst); + inst->advancePC(pc); + tc->pcState(pc); +} + +template +void +AbortFault::invoke(ThreadContext *tc, StaticInstPtr inst) +{ + ArmFaultVals::invoke(tc, inst); + FSR fsr = 0; + fsr.fsLow = bits(status, 3, 0); + fsr.fsHigh = bits(status, 4); + fsr.domain = domain; + fsr.wnr = (write ? 1 : 0); + fsr.ext = 0; + tc->setMiscReg(T::FsrIndex, fsr); + tc->setMiscReg(T::FarIndex, faultAddr); + + DPRINTF(Faults, "Abort Fault fsr=%#x faultAddr=%#x\n", fsr, faultAddr); +} + +void +FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) { + DPRINTF(Faults, "Invoking FlushPipe Fault\n"); + + // Set the PC to the next instruction of the faulting instruction. + // Net effect is simply squashing all instructions behind and + // start refetching from the next instruction. + PCState pc = tc->pcState(); + assert(inst); + inst->advancePC(pc); + tc->pcState(pc); +} + +template void AbortFault::invoke(ThreadContext *tc, + StaticInstPtr inst); +template void AbortFault::invoke(ThreadContext *tc, + StaticInstPtr inst); + +void +ArmSev::invoke(ThreadContext *tc, StaticInstPtr inst) { + DPRINTF(Faults, "Invoking ArmSev Fault\n"); + if (!FullSystem) + return; + + // Set sev_mailbox to 1, clear the pending interrupt from remote + // SEV execution and let pipeline continue as pcState is still + // valid. + tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); + tc->getCpuPtr()->clearInterrupt(INT_SEV, 0); +} + +// return via SUBS pc, lr, xxx; rfe, movs, ldm + +} // namespace ArmISA diff --git a/simulators/gem5/src/arch/arm/faults.hh b/simulators/gem5/src/arch/arm/faults.hh new file mode 100644 index 00000000..9858e52e --- /dev/null +++ b/simulators/gem5/src/arch/arm/faults.hh @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Gabe Black + */ + +#ifndef __ARM_FAULTS_HH__ +#define __ARM_FAULTS_HH__ + +#include "arch/arm/miscregs.hh" +#include "arch/arm/types.hh" +#include "base/misc.hh" +#include "sim/faults.hh" +#include "sim/full_system.hh" + +// The design of the "name" and "vect" functions is in sim/faults.hh + +namespace ArmISA +{ +typedef const Addr FaultOffset; + +class ArmFault : public FaultBase +{ + protected: + Addr getVector(ThreadContext *tc); + + public: + enum StatusEncoding + { + // Fault Status register encodings + // ARM ARM B3.9.4 + AlignmentFault = 0x1, + DebugEvent = 0x2, + AccessFlag0 = 0x3, + InstructionCacheMaintenance = 0x4, + Translation0 = 0x5, + AccessFlag1 = 0x6, + Translation1 = 0x7, + SynchronousExternalAbort0 = 0x8, + Domain0 = 0x9, + SynchronousExternalAbort1 = 0x8, + Domain1 = 0xb, + TranslationTableWalkExtAbt0 = 0xc, + Permission0 = 0xd, + TranslationTableWalkExtAbt1 = 0xe, + Permission1 = 0xf, + AsynchronousExternalAbort = 0x16, + MemoryAccessAsynchronousParityError = 0x18, + MemoryAccessSynchronousParityError = 0x19, + TranslationTableWalkPrtyErr0 = 0x1c, + TranslationTableWalkPrtyErr1 = 0x1e, + + // not a real fault. This is a status code + // to allow the translation function to inform + // the memory access function not to proceed + // for a Prefetch that misses in the TLB. + PrefetchTLBMiss = 0x1f, + PrefetchUncacheable = 0x20 + }; + + struct FaultVals + { + const FaultName name; + const FaultOffset offset; + const OperatingMode nextMode; + const uint8_t armPcOffset; + const uint8_t thumbPcOffset; + const bool abortDisable; + const bool fiqDisable; + FaultStat count; + }; + + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); + virtual FaultStat& countStat() = 0; + virtual FaultOffset offset() = 0; + virtual OperatingMode nextMode() = 0; + virtual uint8_t armPcOffset() = 0; + virtual uint8_t thumbPcOffset() = 0; + virtual bool abortDisable() = 0; + virtual bool fiqDisable() = 0; +}; + +template +class ArmFaultVals : public ArmFault +{ + protected: + static FaultVals vals; + + public: + FaultName name() const { return vals.name; } + FaultStat & countStat() {return vals.count;} + FaultOffset offset() { return vals.offset; } + OperatingMode nextMode() { return vals.nextMode; } + uint8_t armPcOffset() { return vals.armPcOffset; } + uint8_t thumbPcOffset() { return vals.thumbPcOffset; } + bool abortDisable() { return vals.abortDisable; } + bool fiqDisable() { return vals.fiqDisable; } +}; + +class Reset : public ArmFaultVals +{ + public: + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class UndefinedInstruction : public ArmFaultVals +{ + protected: + ExtMachInst machInst; + bool unknown; + const char *mnemonic; + bool disabled; + + public: + UndefinedInstruction(ExtMachInst _machInst, + bool _unknown, + const char *_mnemonic = NULL, + bool _disabled = false) : + machInst(_machInst), unknown(_unknown), + mnemonic(_mnemonic), disabled(_disabled) + { + } + UndefinedInstruction() : + machInst(0), unknown(false), mnemonic("undefined"), disabled(false) + {} + + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class SupervisorCall : public ArmFaultVals +{ + protected: + ExtMachInst machInst; + + public: + SupervisorCall(ExtMachInst _machInst) : machInst(_machInst) + {} + SupervisorCall() : machInst(0) + {} + + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +template +class AbortFault : public ArmFaultVals +{ + protected: + Addr faultAddr; + bool write; + uint8_t domain; + uint8_t status; + + public: + AbortFault(Addr _faultAddr, bool _write, + uint8_t _domain, uint8_t _status) : + faultAddr(_faultAddr), write(_write), + domain(_domain), status(_status) + {} + + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class PrefetchAbort : public AbortFault +{ + public: + static const MiscRegIndex FsrIndex = MISCREG_IFSR; + static const MiscRegIndex FarIndex = MISCREG_IFAR; + + PrefetchAbort(Addr _addr, uint8_t _status) : + AbortFault(_addr, false, 0, _status) + {} +}; + +class DataAbort : public AbortFault +{ + public: + static const MiscRegIndex FsrIndex = MISCREG_DFSR; + static const MiscRegIndex FarIndex = MISCREG_DFAR; + + DataAbort(Addr _addr, uint8_t _domain, bool _write, uint8_t _status) : + AbortFault(_addr, _write, _domain, _status) + {} +}; + +class Interrupt : public ArmFaultVals {}; +class FastInterrupt : public ArmFaultVals {}; + +// A fault that flushes the pipe, excluding the faulting instructions +class FlushPipe : public ArmFaultVals +{ + public: + FlushPipe() {} + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +// A fault that flushes the pipe, excluding the faulting instructions +class ArmSev : public ArmFaultVals +{ + public: + ArmSev () {} + void invoke(ThreadContext *tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +} // namespace ArmISA + +#endif // __ARM_FAULTS_HH__ diff --git a/simulators/gem5/src/arch/arm/insts/branch.hh b/simulators/gem5/src/arch/arm/insts/branch.hh new file mode 100644 index 00000000..cc320dbf --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/branch.hh @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ +#ifndef __ARCH_ARM_INSTS_BRANCH_HH__ +#define __ARCH_ARM_INSTS_BRANCH_HH__ + +#include "arch/arm/insts/pred_inst.hh" + +namespace ArmISA +{ +// Branch to a target computed with an immediate +class BranchImm : public PredOp +{ + protected: + int32_t imm; + + public: + BranchImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + int32_t _imm) : + PredOp(mnem, _machInst, __opClass), imm(_imm) + {} + +}; + +// Conditionally Branch to a target computed with an immediate +class BranchImmCond : public BranchImm +{ + public: + BranchImmCond(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + int32_t _imm, ConditionCode _condCode) : + BranchImm(mnem, _machInst, __opClass, _imm) + { + // Only update if this isn't part of an IT block + if (!machInst.itstateMask) + condCode = _condCode; + } +}; + +// Branch to a target computed with a register +class BranchReg : public PredOp +{ + protected: + IntRegIndex op1; + + public: + BranchReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), op1(_op1) + {} +}; + +// Conditionally Branch to a target computed with a register +class BranchRegCond : public BranchReg +{ + public: + BranchRegCond(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1, ConditionCode _condCode) : + BranchReg(mnem, _machInst, __opClass, _op1) + { + // Only update if this isn't part of an IT block + if (!machInst.itstateMask) + condCode = _condCode; + } +}; + +// Branch to a target computed with two registers +class BranchRegReg : public PredOp +{ + protected: + IntRegIndex op1; + IntRegIndex op2; + + public: + BranchRegReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1, IntRegIndex _op2) : + PredOp(mnem, _machInst, __opClass), op1(_op1), op2(_op2) + {} +}; + +// Branch to a target computed with an immediate and a register +class BranchImmReg : public PredOp +{ + protected: + int32_t imm; + IntRegIndex op1; + + public: + BranchImmReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + int32_t _imm, IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), imm(_imm), op1(_op1) + {} +}; + +} + +#endif //__ARCH_ARM_INSTS_BRANCH_HH__ diff --git a/simulators/gem5/src/arch/arm/insts/macromem.cc b/simulators/gem5/src/arch/arm/insts/macromem.cc new file mode 100644 index 00000000..e1b75420 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/macromem.cc @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ + +#include + +#include "arch/arm/insts/macromem.hh" +#include "arch/arm/generated/decoder.hh" + +using namespace std; +using namespace ArmISAInst; + +namespace ArmISA +{ + +MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst, + OpClass __opClass, IntRegIndex rn, + bool index, bool up, bool user, bool writeback, + bool load, uint32_t reglist) : + PredMacroOp(mnem, machInst, __opClass) +{ + uint32_t regs = reglist; + uint32_t ones = number_of_ones(reglist); + // Remember that writeback adds a uop or two and the temp register adds one + numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1; + + // It's technically legal to do a lot of nothing + if (!ones) + numMicroops = 1; + + microOps = new StaticInstPtr[numMicroops]; + uint32_t addr = 0; + + if (!up) + addr = (ones << 2) - 4; + + if (!index) + addr += 4; + + StaticInstPtr *uop = microOps; + + // Add 0 to Rn and stick it in ureg0. + // This is equivalent to a move. + *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0); + + unsigned reg = 0; + unsigned regIdx = 0; + bool force_user = user & !bits(reglist, 15); + bool exception_ret = user & bits(reglist, 15); + + for (int i = 0; i < ones; i++) { + // Find the next register. + while (!bits(regs, reg)) + reg++; + replaceBits(regs, reg, 0); + + regIdx = reg; + if (force_user) { + regIdx = intRegInMode(MODE_USER, regIdx); + } + + if (load) { + if (writeback && i == ones - 1) { + // If it's a writeback and this is the last register + // do the load into a temporary register which we'll move + // into the final one later + *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0, + up, addr); + } else { + // Otherwise just do it normally + if (reg == INTREG_PC && exception_ret) { + // This must be the exception return form of ldm. + *++uop = new MicroLdrRetUop(machInst, regIdx, + INTREG_UREG0, up, addr); + } else { + *++uop = new MicroLdrUop(machInst, regIdx, + INTREG_UREG0, up, addr); + } + } + } else { + *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr); + } + + if (up) + addr += 4; + else + addr -= 4; + } + + if (writeback && ones) { + // put the register update after we're done all loading + if (up) + *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4); + else + *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4); + + // If this was a load move the last temporary value into place + // this way we can't take an exception after we update the base + // register. + if (load && reg == INTREG_PC && exception_ret) { + *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1); + } else if (load) { + *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1); + if (reg == INTREG_PC) { + (*uop)->setFlag(StaticInst::IsControl); + (*uop)->setFlag(StaticInst::IsCondControl); + (*uop)->setFlag(StaticInst::IsIndirectControl); + // This is created as a RAS POP + if (rn == INTREG_SP) + (*uop)->setFlag(StaticInst::IsReturn); + + } + } + } + + (*uop)->setLastMicroop(); + + for (StaticInstPtr *curUop = microOps; + !(*curUop)->isLastMicroop(); curUop++) { + MicroOp * uopPtr = dynamic_cast(curUop->get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } +} + +VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, + unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, + unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : + PredMacroOp(mnem, machInst, __opClass) +{ + assert(regs > 0 && regs <= 4); + assert(regs % elems == 0); + + numMicroops = (regs > 2) ? 2 : 1; + bool wb = (rm != 15); + bool deinterleave = (elems > 1); + + if (wb) numMicroops++; + if (deinterleave) numMicroops += (regs / elems); + microOps = new StaticInstPtr[numMicroops]; + + RegIndex rMid = deinterleave ? NumFloatArchRegs : vd * 2; + + uint32_t noAlign = TLB::MustBeOne; + + unsigned uopIdx = 0; + switch (regs) { + case 4: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid + 4, rn, 16, noAlign); + break; + case 3: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid + 4, rn, 16, noAlign); + break; + case 2: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + break; + case 1: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + break; + default: + // Unknown number of registers + microOps[uopIdx++] = new Unknown(machInst); + } + if (wb) { + if (rm != 15 && rm != 13) { + microOps[uopIdx++] = + new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); + } else { + microOps[uopIdx++] = + new MicroAddiUop(machInst, rn, rn, regs * 8); + } + } + if (deinterleave) { + switch (elems) { + case 4: + assert(regs == 4); + microOps[uopIdx++] = newNeonMixInst( + size, machInst, vd * 2, rMid, inc * 2); + break; + case 3: + assert(regs == 3); + microOps[uopIdx++] = newNeonMixInst( + size, machInst, vd * 2, rMid, inc * 2); + break; + case 2: + assert(regs == 4 || regs == 2); + if (regs == 4) { + microOps[uopIdx++] = newNeonMixInst( + size, machInst, vd * 2, rMid, inc * 2); + microOps[uopIdx++] = newNeonMixInst( + size, machInst, vd * 2 + 2, rMid + 4, inc * 2); + } else { + microOps[uopIdx++] = newNeonMixInst( + size, machInst, vd * 2, rMid, inc * 2); + } + break; + default: + // Bad number of elements to deinterleave + microOps[uopIdx++] = new Unknown(machInst); + } + } + assert(uopIdx == numMicroops); + + for (unsigned i = 0; i < numMicroops - 1; i++) { + MicroOp * uopPtr = dynamic_cast(microOps[i].get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } + microOps[numMicroops - 1]->setLastMicroop(); +} + +VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst, + OpClass __opClass, bool all, unsigned elems, + RegIndex rn, RegIndex vd, unsigned regs, + unsigned inc, uint32_t size, uint32_t align, + RegIndex rm, unsigned lane) : + PredMacroOp(mnem, machInst, __opClass) +{ + assert(regs > 0 && regs <= 4); + assert(regs % elems == 0); + + unsigned eBytes = (1 << size); + unsigned loadSize = eBytes * elems; + unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) / + sizeof(FloatRegBits); + + assert(loadRegs > 0 && loadRegs <= 4); + + numMicroops = 1; + bool wb = (rm != 15); + + if (wb) numMicroops++; + numMicroops += (regs / elems); + microOps = new StaticInstPtr[numMicroops]; + + RegIndex ufp0 = NumFloatArchRegs; + + unsigned uopIdx = 0; + switch (loadSize) { + case 1: + microOps[uopIdx++] = new MicroLdrNeon1Uop( + machInst, ufp0, rn, 0, align); + break; + case 2: + if (eBytes == 2) { + microOps[uopIdx++] = new MicroLdrNeon2Uop( + machInst, ufp0, rn, 0, align); + } else { + microOps[uopIdx++] = new MicroLdrNeon2Uop( + machInst, ufp0, rn, 0, align); + } + break; + case 3: + microOps[uopIdx++] = new MicroLdrNeon3Uop( + machInst, ufp0, rn, 0, align); + break; + case 4: + switch (eBytes) { + case 1: + microOps[uopIdx++] = new MicroLdrNeon4Uop( + machInst, ufp0, rn, 0, align); + break; + case 2: + microOps[uopIdx++] = new MicroLdrNeon4Uop( + machInst, ufp0, rn, 0, align); + break; + case 4: + microOps[uopIdx++] = new MicroLdrNeon4Uop( + machInst, ufp0, rn, 0, align); + break; + } + break; + case 6: + microOps[uopIdx++] = new MicroLdrNeon6Uop( + machInst, ufp0, rn, 0, align); + break; + case 8: + switch (eBytes) { + case 2: + microOps[uopIdx++] = new MicroLdrNeon8Uop( + machInst, ufp0, rn, 0, align); + break; + case 4: + microOps[uopIdx++] = new MicroLdrNeon8Uop( + machInst, ufp0, rn, 0, align); + break; + } + break; + case 12: + microOps[uopIdx++] = new MicroLdrNeon12Uop( + machInst, ufp0, rn, 0, align); + break; + case 16: + microOps[uopIdx++] = new MicroLdrNeon16Uop( + machInst, ufp0, rn, 0, align); + break; + default: + // Unrecognized load size + microOps[uopIdx++] = new Unknown(machInst); + } + if (wb) { + if (rm != 15 && rm != 13) { + microOps[uopIdx++] = + new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); + } else { + microOps[uopIdx++] = + new MicroAddiUop(machInst, rn, rn, loadSize); + } + } + switch (elems) { + case 4: + assert(regs == 4); + switch (size) { + case 0: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to8Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + case 1: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to8Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + case 2: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon4to8Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + break; + case 3: + assert(regs == 3); + switch (size) { + case 0: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to6Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + case 1: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to6Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + case 2: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon4to6Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + break; + case 2: + assert(regs == 2); + assert(loadRegs <= 2); + switch (size) { + case 0: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to4Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + case 1: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to4Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + case 2: + if (all) { + microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop( + machInst, vd * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = new MicroUnpackNeon2to4Uop( + machInst, vd * 2, ufp0, inc * 2, lane); + } + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + break; + case 1: + assert(regs == 1 || (all && regs == 2)); + assert(loadRegs <= 2); + for (unsigned offset = 0; offset < regs; offset++) { + switch (size) { + case 0: + if (all) { + microOps[uopIdx++] = + new MicroUnpackAllNeon2to2Uop( + machInst, (vd + offset) * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = + new MicroUnpackNeon2to2Uop( + machInst, (vd + offset) * 2, ufp0, inc * 2, lane); + } + break; + case 1: + if (all) { + microOps[uopIdx++] = + new MicroUnpackAllNeon2to2Uop( + machInst, (vd + offset) * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = + new MicroUnpackNeon2to2Uop( + machInst, (vd + offset) * 2, ufp0, inc * 2, lane); + } + break; + case 2: + if (all) { + microOps[uopIdx++] = + new MicroUnpackAllNeon2to2Uop( + machInst, (vd + offset) * 2, ufp0, inc * 2); + } else { + microOps[uopIdx++] = + new MicroUnpackNeon2to2Uop( + machInst, (vd + offset) * 2, ufp0, inc * 2, lane); + } + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + } + break; + default: + // Bad number of elements to unpack + microOps[uopIdx++] = new Unknown(machInst); + } + assert(uopIdx == numMicroops); + + for (unsigned i = 0; i < numMicroops - 1; i++) { + MicroOp * uopPtr = dynamic_cast(microOps[i].get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } + microOps[numMicroops - 1]->setLastMicroop(); +} + +VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, + unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, + unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : + PredMacroOp(mnem, machInst, __opClass) +{ + assert(regs > 0 && regs <= 4); + assert(regs % elems == 0); + + numMicroops = (regs > 2) ? 2 : 1; + bool wb = (rm != 15); + bool interleave = (elems > 1); + + if (wb) numMicroops++; + if (interleave) numMicroops += (regs / elems); + microOps = new StaticInstPtr[numMicroops]; + + uint32_t noAlign = TLB::MustBeOne; + + RegIndex rMid = interleave ? NumFloatArchRegs : vd * 2; + + unsigned uopIdx = 0; + if (interleave) { + switch (elems) { + case 4: + assert(regs == 4); + microOps[uopIdx++] = newNeonMixInst( + size, machInst, rMid, vd * 2, inc * 2); + break; + case 3: + assert(regs == 3); + microOps[uopIdx++] = newNeonMixInst( + size, machInst, rMid, vd * 2, inc * 2); + break; + case 2: + assert(regs == 4 || regs == 2); + if (regs == 4) { + microOps[uopIdx++] = newNeonMixInst( + size, machInst, rMid, vd * 2, inc * 2); + microOps[uopIdx++] = newNeonMixInst( + size, machInst, rMid + 4, vd * 2 + 2, inc * 2); + } else { + microOps[uopIdx++] = newNeonMixInst( + size, machInst, rMid, vd * 2, inc * 2); + } + break; + default: + // Bad number of elements to interleave + microOps[uopIdx++] = new Unknown(machInst); + } + } + switch (regs) { + case 4: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid + 4, rn, 16, noAlign); + break; + case 3: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid + 4, rn, 16, noAlign); + break; + case 2: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + break; + case 1: + microOps[uopIdx++] = newNeonMemInst( + size, machInst, rMid, rn, 0, align); + break; + default: + // Unknown number of registers + microOps[uopIdx++] = new Unknown(machInst); + } + if (wb) { + if (rm != 15 && rm != 13) { + microOps[uopIdx++] = + new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); + } else { + microOps[uopIdx++] = + new MicroAddiUop(machInst, rn, rn, regs * 8); + } + } + assert(uopIdx == numMicroops); + + for (unsigned i = 0; i < numMicroops - 1; i++) { + MicroOp * uopPtr = dynamic_cast(microOps[i].get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } + microOps[numMicroops - 1]->setLastMicroop(); +} + +VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst, + OpClass __opClass, bool all, unsigned elems, + RegIndex rn, RegIndex vd, unsigned regs, + unsigned inc, uint32_t size, uint32_t align, + RegIndex rm, unsigned lane) : + PredMacroOp(mnem, machInst, __opClass) +{ + assert(!all); + assert(regs > 0 && regs <= 4); + assert(regs % elems == 0); + + unsigned eBytes = (1 << size); + unsigned storeSize = eBytes * elems; + unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) / + sizeof(FloatRegBits); + + assert(storeRegs > 0 && storeRegs <= 4); + + numMicroops = 1; + bool wb = (rm != 15); + + if (wb) numMicroops++; + numMicroops += (regs / elems); + microOps = new StaticInstPtr[numMicroops]; + + RegIndex ufp0 = NumFloatArchRegs; + + unsigned uopIdx = 0; + switch (elems) { + case 4: + assert(regs == 4); + switch (size) { + case 0: + microOps[uopIdx++] = new MicroPackNeon8to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + case 1: + microOps[uopIdx++] = new MicroPackNeon8to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + case 2: + microOps[uopIdx++] = new MicroPackNeon8to4Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + break; + case 3: + assert(regs == 3); + switch (size) { + case 0: + microOps[uopIdx++] = new MicroPackNeon6to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + case 1: + microOps[uopIdx++] = new MicroPackNeon6to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + case 2: + microOps[uopIdx++] = new MicroPackNeon6to4Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + break; + case 2: + assert(regs == 2); + assert(storeRegs <= 2); + switch (size) { + case 0: + microOps[uopIdx++] = new MicroPackNeon4to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + case 1: + microOps[uopIdx++] = new MicroPackNeon4to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + case 2: + microOps[uopIdx++] = new MicroPackNeon4to2Uop( + machInst, ufp0, vd * 2, inc * 2, lane); + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + break; + case 1: + assert(regs == 1 || (all && regs == 2)); + assert(storeRegs <= 2); + for (unsigned offset = 0; offset < regs; offset++) { + switch (size) { + case 0: + microOps[uopIdx++] = new MicroPackNeon2to2Uop( + machInst, ufp0, (vd + offset) * 2, inc * 2, lane); + break; + case 1: + microOps[uopIdx++] = new MicroPackNeon2to2Uop( + machInst, ufp0, (vd + offset) * 2, inc * 2, lane); + break; + case 2: + microOps[uopIdx++] = new MicroPackNeon2to2Uop( + machInst, ufp0, (vd + offset) * 2, inc * 2, lane); + break; + default: + // Bad size + microOps[uopIdx++] = new Unknown(machInst); + break; + } + } + break; + default: + // Bad number of elements to unpack + microOps[uopIdx++] = new Unknown(machInst); + } + switch (storeSize) { + case 1: + microOps[uopIdx++] = new MicroStrNeon1Uop( + machInst, ufp0, rn, 0, align); + break; + case 2: + if (eBytes == 2) { + microOps[uopIdx++] = new MicroStrNeon2Uop( + machInst, ufp0, rn, 0, align); + } else { + microOps[uopIdx++] = new MicroStrNeon2Uop( + machInst, ufp0, rn, 0, align); + } + break; + case 3: + microOps[uopIdx++] = new MicroStrNeon3Uop( + machInst, ufp0, rn, 0, align); + break; + case 4: + switch (eBytes) { + case 1: + microOps[uopIdx++] = new MicroStrNeon4Uop( + machInst, ufp0, rn, 0, align); + break; + case 2: + microOps[uopIdx++] = new MicroStrNeon4Uop( + machInst, ufp0, rn, 0, align); + break; + case 4: + microOps[uopIdx++] = new MicroStrNeon4Uop( + machInst, ufp0, rn, 0, align); + break; + } + break; + case 6: + microOps[uopIdx++] = new MicroStrNeon6Uop( + machInst, ufp0, rn, 0, align); + break; + case 8: + switch (eBytes) { + case 2: + microOps[uopIdx++] = new MicroStrNeon8Uop( + machInst, ufp0, rn, 0, align); + break; + case 4: + microOps[uopIdx++] = new MicroStrNeon8Uop( + machInst, ufp0, rn, 0, align); + break; + } + break; + case 12: + microOps[uopIdx++] = new MicroStrNeon12Uop( + machInst, ufp0, rn, 0, align); + break; + case 16: + microOps[uopIdx++] = new MicroStrNeon16Uop( + machInst, ufp0, rn, 0, align); + break; + default: + // Bad store size + microOps[uopIdx++] = new Unknown(machInst); + } + if (wb) { + if (rm != 15 && rm != 13) { + microOps[uopIdx++] = + new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); + } else { + microOps[uopIdx++] = + new MicroAddiUop(machInst, rn, rn, storeSize); + } + } + assert(uopIdx == numMicroops); + + for (unsigned i = 0; i < numMicroops - 1; i++) { + MicroOp * uopPtr = dynamic_cast(microOps[i].get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } + microOps[numMicroops - 1]->setLastMicroop(); +} + +MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst, + OpClass __opClass, IntRegIndex rn, + RegIndex vd, bool single, bool up, + bool writeback, bool load, uint32_t offset) : + PredMacroOp(mnem, machInst, __opClass) +{ + int i = 0; + + // The lowest order bit selects fldmx (set) or fldmd (clear). These seem + // to be functionally identical except that fldmx is deprecated. For now + // we'll assume they're otherwise interchangable. + int count = (single ? offset : (offset / 2)); + if (count == 0 || count > NumFloatArchRegs) + warn_once("Bad offset field for VFP load/store multiple.\n"); + if (count == 0) { + // Force there to be at least one microop so the macroop makes sense. + writeback = true; + } + if (count > NumFloatArchRegs) + count = NumFloatArchRegs; + + numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0); + microOps = new StaticInstPtr[numMicroops]; + + int64_t addr = 0; + + if (!up) + addr = 4 * offset; + + bool tempUp = up; + for (int j = 0; j < count; j++) { + if (load) { + if (single) { + microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn, + tempUp, addr); + } else { + microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn, + tempUp, addr); + microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp, + addr + (up ? 4 : -4)); + } + } else { + if (single) { + microOps[i++] = new MicroStrFpUop(machInst, vd++, rn, + tempUp, addr); + } else { + microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn, + tempUp, addr); + microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp, + addr + (up ? 4 : -4)); + } + } + if (!tempUp) { + addr -= (single ? 4 : 8); + // The microops don't handle negative displacement, so turn if we + // hit zero, flip polarity and start adding. + if (addr <= 0) { + tempUp = true; + addr = -addr; + } + } else { + addr += (single ? 4 : 8); + } + } + + if (writeback) { + if (up) { + microOps[i++] = + new MicroAddiUop(machInst, rn, rn, 4 * offset); + } else { + microOps[i++] = + new MicroSubiUop(machInst, rn, rn, 4 * offset); + } + } + + assert(numMicroops == i); + microOps[numMicroops - 1]->setLastMicroop(); + + for (StaticInstPtr *curUop = microOps; + !(*curUop)->isLastMicroop(); curUop++) { + MicroOp * uopPtr = dynamic_cast(curUop->get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } +} + +std::string +MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, ura); + ss << ", "; + printReg(ss, urb); + ss << ", "; + ccprintf(ss, "#%d", imm); + return ss.str(); +} + +std::string +MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + ss << "[PC,CPSR]"; + return ss.str(); +} + +std::string +MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, ura); + ss << ", "; + printReg(ss, urb); + return ss.str(); +} + +std::string +MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, ura); + ss << ", "; + printReg(ss, urb); + ss << ", "; + printReg(ss, urc); + return ss.str(); +} + +std::string +MicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, ura); + ss << ", ["; + printReg(ss, urb); + ss << ", "; + ccprintf(ss, "#%d", imm); + ss << "]"; + return ss.str(); +} + +} diff --git a/simulators/gem5/src/arch/arm/insts/macromem.hh b/simulators/gem5/src/arch/arm/insts/macromem.hh new file mode 100644 index 00000000..4933a1e7 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/macromem.hh @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ +#ifndef __ARCH_ARM_MACROMEM_HH__ +#define __ARCH_ARM_MACROMEM_HH__ + +#include "arch/arm/insts/pred_inst.hh" +#include "arch/arm/tlb.hh" + +namespace ArmISA +{ + +static inline unsigned int +number_of_ones(int32_t val) +{ + uint32_t ones = 0; + for (int i = 0; i < 32; i++ ) + { + if ( val & (1< +class MemoryOffset : public Base +{ + protected: + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _result, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _result, + _dest, _dest2, _base, _add, _imm) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + this->printInst(ss, Memory::AddrMd_Offset); + return ss.str(); + } +}; + +template +class MemoryPreIndex : public Base +{ + protected: + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _result, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _result, + _dest, _dest2, _base, _add, _imm) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + this->printInst(ss, Memory::AddrMd_PreIndex); + return ss.str(); + } +}; + +template +class MemoryPostIndex : public Base +{ + protected: + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _result, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _result, + _dest, _dest2, _base, _add, _imm) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + this->printInst(ss, Memory::AddrMd_PostIndex); + return ss.str(); + } +}; +} + +#endif //__ARCH_ARM_INSTS_MEM_HH__ diff --git a/simulators/gem5/src/arch/arm/insts/misc.cc b/simulators/gem5/src/arch/arm/insts/misc.cc new file mode 100644 index 00000000..7d383a87 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/misc.cc @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/arm/insts/misc.hh" + +std::string +MrsOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + bool foundPsr = false; + for (unsigned i = 0; i < numSrcRegs(); i++) { + int idx = srcRegIdx(i); + if (idx < Ctrl_Base_DepTag) { + continue; + } + idx -= Ctrl_Base_DepTag; + if (idx == MISCREG_CPSR) { + ss << "cpsr"; + foundPsr = true; + break; + } + if (idx == MISCREG_SPSR) { + ss << "spsr"; + foundPsr = true; + break; + } + } + if (!foundPsr) { + ss << "????"; + } + return ss.str(); +} + +void +MsrBase::printMsrBase(std::ostream &os) const +{ + printMnemonic(os); + bool apsr = false; + bool foundPsr = false; + for (unsigned i = 0; i < numDestRegs(); i++) { + int idx = destRegIdx(i); + if (idx < Ctrl_Base_DepTag) { + continue; + } + idx -= Ctrl_Base_DepTag; + if (idx == MISCREG_CPSR) { + os << "cpsr_"; + foundPsr = true; + break; + } + if (idx == MISCREG_SPSR) { + if (bits(byteMask, 1, 0)) { + os << "spsr_"; + } else { + os << "apsr_"; + apsr = true; + } + foundPsr = true; + break; + } + } + if (!foundPsr) { + os << "????"; + return; + } + if (bits(byteMask, 3)) { + if (apsr) { + os << "nzcvq"; + } else { + os << "f"; + } + } + if (bits(byteMask, 2)) { + if (apsr) { + os << "g"; + } else { + os << "s"; + } + } + if (bits(byteMask, 1)) { + os << "x"; + } + if (bits(byteMask, 0)) { + os << "c"; + } +} + +std::string +MsrImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMsrBase(ss); + ccprintf(ss, ", #%#x", imm); + return ss.str(); +} + +std::string +MsrRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMsrBase(ss); + ss << ", "; + printReg(ss, op1); + return ss.str(); +} + +std::string +ImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + ccprintf(ss, "#%d", imm); + return ss.str(); +} + +std::string +RegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +RegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + return ss.str(); +} + +std::string +RegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ss << ", "; + printReg(ss, op2); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +RegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ss << ", "; + printReg(ss, op2); + ss << ", "; + printReg(ss, op3); + return ss.str(); +} + +std::string +RegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ss << ", "; + printReg(ss, op2); + return ss.str(); +} + +std::string +RegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +RegRegImmImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ccprintf(ss, ", #%d, #%d", imm1, imm2); + return ss.str(); +} + +std::string +RegImmRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ccprintf(ss, ", #%d, ", imm); + printReg(ss, op1); + return ss.str(); +} + +std::string +RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ccprintf(ss, ", #%d, ", imm); + printShiftOperand(ss, op1, true, shiftAmt, INTREG_ZERO, shiftType); + printReg(ss, op1); + return ss.str(); +} + +std::string +UnknownOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + return csprintf("%-10s (inst %#08x)", "unknown", machInst); +} diff --git a/simulators/gem5/src/arch/arm/insts/misc.hh b/simulators/gem5/src/arch/arm/insts/misc.hh new file mode 100644 index 00000000..c9e114f8 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/misc.hh @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ARM_INSTS_MISC_HH__ +#define __ARCH_ARM_INSTS_MISC_HH__ + +#include "arch/arm/insts/pred_inst.hh" + +class MrsOp : public PredOp +{ + protected: + IntRegIndex dest; + + MrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest) : + PredOp(mnem, _machInst, __opClass), dest(_dest) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class MsrBase : public PredOp +{ + protected: + uint8_t byteMask; + + MsrBase(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint8_t _byteMask) : + PredOp(mnem, _machInst, __opClass), byteMask(_byteMask) + {} + + void printMsrBase(std::ostream &os) const; +}; + +class MsrImmOp : public MsrBase +{ + protected: + uint32_t imm; + + MsrImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint32_t _imm, uint8_t _byteMask) : + MsrBase(mnem, _machInst, __opClass, _byteMask), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class MsrRegOp : public MsrBase +{ + protected: + IntRegIndex op1; + + MsrRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1, uint8_t _byteMask) : + MsrBase(mnem, _machInst, __opClass, _byteMask), op1(_op1) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class ImmOp : public PredOp +{ + protected: + uint64_t imm; + + ImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegImmOp : public PredOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + + RegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + + RegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegImmRegOp : public PredOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + IntRegIndex op1; + + RegImmRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm, IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), imm(_imm), op1(_op1) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegRegImmOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + uint64_t imm; + + RegRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegRegRegOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + IntRegIndex op3; + + RegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + IntRegIndex _op2, IntRegIndex _op3) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), op3(_op3) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegRegOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + + RegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegImmOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + uint64_t imm; + + RegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegImmImmOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + uint64_t imm1; + uint64_t imm2; + + RegRegImmImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm1, uint64_t _imm2) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm1(_imm1), imm2(_imm2) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegImmRegShiftOp : public PredOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + IntRegIndex op1; + int32_t shiftAmt; + ArmShiftType shiftType; + + RegImmRegShiftOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm, IntRegIndex _op1, + int32_t _shiftAmt, ArmShiftType _shiftType) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), imm(_imm), op1(_op1), + shiftAmt(_shiftAmt), shiftType(_shiftType) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class UnknownOp : public PredOp +{ + protected: + + UnknownOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +#endif diff --git a/simulators/gem5/src/arch/arm/insts/mult.hh b/simulators/gem5/src/arch/arm/insts/mult.hh new file mode 100644 index 00000000..9548766b --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/mult.hh @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ +#ifndef __ARCH_ARM_INSTS_MULT_HH__ +#define __ARCH_ARM_INSTS_MULT_HH__ + +#include "arch/arm/insts/static_inst.hh" +#include "base/trace.hh" + +namespace ArmISA +{ + +/** + * Base class for multipy instructions using three registers. + */ +class Mult3 : public PredOp +{ + protected: + IntRegIndex reg0, reg1, reg2; + + Mult3(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _reg0, IntRegIndex _reg1, IntRegIndex _reg2) : + PredOp(mnem, _machInst, __opClass), + reg0(_reg0), reg1(_reg1), reg2(_reg2) + {} +}; + +/** + * Base class for multipy instructions using four registers. + */ +class Mult4 : public Mult3 +{ + protected: + IntRegIndex reg3; + + Mult4(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _reg0, IntRegIndex _reg1, + IntRegIndex _reg2, IntRegIndex _reg3) : + Mult3(mnem, _machInst, __opClass, _reg0, _reg1, _reg2), reg3(_reg3) + {} +}; +} + +#endif //__ARCH_ARM_INSTS_MULT_HH__ diff --git a/simulators/gem5/src/arch/arm/insts/pred_inst.cc b/simulators/gem5/src/arch/arm/insts/pred_inst.cc new file mode 100644 index 00000000..049c42f0 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/pred_inst.cc @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ + +#include "arch/arm/insts/pred_inst.hh" + +namespace ArmISA +{ +std::string +PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + unsigned rotate = machInst.rotate * 2; + uint32_t imm = machInst.imm; + imm = (imm << (32 - rotate)) | (imm >> rotate); + printDataInst(ss, false, machInst.opcode4 == 0, machInst.sField, + (IntRegIndex)(uint32_t)machInst.rd, + (IntRegIndex)(uint32_t)machInst.rn, + (IntRegIndex)(uint32_t)machInst.rm, + (IntRegIndex)(uint32_t)machInst.rs, + machInst.shiftSize, (ArmShiftType)(uint32_t)machInst.shift, + imm); + return ss.str(); +} + +std::string +PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, true, machInst.opcode4 == 0, machInst.sField, + (IntRegIndex)(uint32_t)machInst.rd, + (IntRegIndex)(uint32_t)machInst.rn, + (IntRegIndex)(uint32_t)machInst.rm, + (IntRegIndex)(uint32_t)machInst.rs, + machInst.shiftSize, (ArmShiftType)(uint32_t)machInst.shift, + imm); + return ss.str(); +} + +std::string +DataImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, true, false, /*XXX not really s*/ false, dest, op1, + INTREG_ZERO, INTREG_ZERO, 0, LSL, imm); + return ss.str(); +} + +std::string +DataRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, false, true, /*XXX not really s*/ false, dest, op1, + op2, INTREG_ZERO, shiftAmt, shiftType, 0); + return ss.str(); +} + +std::string +DataRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, false, false, /*XXX not really s*/ false, dest, op1, + op2, shift, 0, shiftType, 0); + return ss.str(); +} + +std::string +PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); +} +} diff --git a/simulators/gem5/src/arch/arm/insts/pred_inst.hh b/simulators/gem5/src/arch/arm/insts/pred_inst.hh new file mode 100644 index 00000000..c441d1f3 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/pred_inst.hh @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ +#ifndef __ARCH_ARM_INSTS_PREDINST_HH__ +#define __ARCH_ARM_INSTS_PREDINST_HH__ + +#include "arch/arm/insts/static_inst.hh" +#include "base/trace.hh" + +namespace ArmISA +{ +static inline uint32_t +rotate_imm(uint32_t immValue, int rotateValue) +{ + return ((immValue >> (rotateValue & 31)) | + (immValue << (32 - (rotateValue & 31)))); +} + +static inline uint32_t +modified_imm(uint8_t ctrlImm, uint8_t dataImm) +{ + uint32_t bigData = dataImm; + uint32_t bigCtrl = ctrlImm; + if (bigCtrl < 4) { + switch (bigCtrl) { + case 0: + return bigData; + case 1: + return bigData | (bigData << 16); + case 2: + return (bigData << 8) | (bigData << 24); + case 3: + return (bigData << 0) | (bigData << 8) | + (bigData << 16) | (bigData << 24); + } + } + bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1); + bigData |= (1 << 7); + return bigData << (32 - bigCtrl); +} + +static inline uint64_t +simd_modified_imm(bool op, uint8_t cmode, uint8_t data, bool &immValid) +{ + uint64_t bigData = data; + immValid = true; + switch (cmode) { + case 0x0: + case 0x1: + bigData = (bigData << 0) | (bigData << 32); + break; + case 0x2: + case 0x3: + bigData = (bigData << 8) | (bigData << 40); + break; + case 0x4: + case 0x5: + bigData = (bigData << 16) | (bigData << 48); + break; + case 0x6: + case 0x7: + bigData = (bigData << 24) | (bigData << 56); + break; + case 0x8: + case 0x9: + bigData = (bigData << 0) | (bigData << 16) | + (bigData << 32) | (bigData << 48); + break; + case 0xa: + case 0xb: + bigData = (bigData << 8) | (bigData << 24) | + (bigData << 40) | (bigData << 56); + break; + case 0xc: + bigData = (0xffULL << 0) | (bigData << 8) | + (0xffULL << 32) | (bigData << 40); + break; + case 0xd: + bigData = (0xffffULL << 0) | (bigData << 16) | + (0xffffULL << 32) | (bigData << 48); + break; + case 0xe: + if (op) { + bigData = 0; + for (int i = 7; i >= 0; i--) { + if (bits(data, i)) { + bigData |= (ULL(0xFF) << (i * 8)); + } + } + } else { + bigData = (bigData << 0) | (bigData << 8) | + (bigData << 16) | (bigData << 24) | + (bigData << 32) | (bigData << 40) | + (bigData << 48) | (bigData << 56); + } + break; + case 0xf: + if (!op) { + uint64_t bVal = bits(bigData, 6) ? (0x1F) : (0x20); + bigData = (bits(bigData, 5, 0) << 19) | + (bVal << 25) | (bits(bigData, 7) << 31); + bigData |= (bigData << 32); + break; + } + // Fall through, immediate encoding is invalid. + default: + immValid = false; + break; + } + return bigData; +} + +static inline uint64_t +vfp_modified_imm(uint8_t data, bool wide) +{ + uint64_t bigData = data; + uint64_t repData; + if (wide) { + repData = bits(data, 6) ? 0xFF : 0; + bigData = (bits(bigData, 5, 0) << 48) | + (repData << 54) | (bits(~bigData, 6) << 62) | + (bits(bigData, 7) << 63); + } else { + repData = bits(data, 6) ? 0x1F : 0; + bigData = (bits(bigData, 5, 0) << 19) | + (repData << 25) | (bits(~bigData, 6) << 30) | + (bits(bigData, 7) << 31); + } + return bigData; +} + + +/** + * Base class for predicated integer operations. + */ +class PredOp : public ArmStaticInst +{ + protected: + + ConditionCode condCode; + + /// Constructor + PredOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + ArmStaticInst(mnem, _machInst, __opClass), + condCode(machInst.itstateMask ? + (ConditionCode)(uint8_t)machInst.itstateCond : + (ConditionCode)(unsigned)machInst.condCode) + { + } +}; + +/** + * Base class for predicated immediate operations. + */ +class PredImmOp : public PredOp +{ + protected: + + uint32_t imm; + uint32_t rotated_imm; + uint32_t rotated_carry; + uint32_t rotate; + + /// Constructor + PredImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + imm(machInst.imm), rotated_imm(0), rotated_carry(0), + rotate(machInst.rotate << 1) + { + rotated_imm = rotate_imm(imm, rotate); + if (rotate != 0) + rotated_carry = bits(rotated_imm, 31); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for predicated integer operations. + */ +class PredIntOp : public PredOp +{ + protected: + + uint32_t shift_size; + uint32_t shift; + + /// Constructor + PredIntOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + shift_size(machInst.shiftSize), shift(machInst.shift) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class DataImmOp : public PredOp +{ + protected: + IntRegIndex dest, op1; + uint32_t imm; + // Whether the carry flag should be modified if that's an option for + // this instruction. + bool rotC; + + DataImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, uint32_t _imm, bool _rotC) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm(_imm), rotC(_rotC) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class DataRegOp : public PredOp +{ + protected: + IntRegIndex dest, op1, op2; + int32_t shiftAmt; + ArmShiftType shiftType; + + DataRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + int32_t _shiftAmt, ArmShiftType _shiftType) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), + shiftAmt(_shiftAmt), shiftType(_shiftType) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class DataRegRegOp : public PredOp +{ + protected: + IntRegIndex dest, op1, op2, shift; + ArmShiftType shiftType; + + DataRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + IntRegIndex _shift, ArmShiftType _shiftType) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), shift(_shift), + shiftType(_shiftType) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for predicated macro-operations. + */ +class PredMacroOp : public PredOp +{ + protected: + + uint32_t numMicroops; + StaticInstPtr * microOps; + + /// Constructor + PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + numMicroops(0) + { + // We rely on the subclasses of this object to handle the + // initialization of the micro-operations, since they are + // all of variable length + flags[IsMacroop] = true; + } + + ~PredMacroOp() + { + if (numMicroops) + delete [] microOps; + } + + StaticInstPtr + fetchMicroop(MicroPC microPC) const + { + assert(microPC < numMicroops); + return microOps[microPC]; + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for predicated micro-operations. + */ +class PredMicroop : public PredOp +{ + /// Constructor + PredMicroop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + { + flags[IsMicroop] = true; + } + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) + pcState.uEnd(); + else + pcState.uAdvance(); + } +}; +} + +#endif //__ARCH_ARM_INSTS_PREDINST_HH__ diff --git a/simulators/gem5/src/arch/arm/insts/static_inst.cc b/simulators/gem5/src/arch/arm/insts/static_inst.cc new file mode 100644 index 00000000..8306c620 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/static_inst.cc @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ + +#include "arch/arm/insts/static_inst.hh" +#include "arch/arm/faults.hh" +#include "base/loader/symtab.hh" +#include "base/condcodes.hh" +#include "base/cprintf.hh" + +namespace ArmISA +{ +// Shift Rm by an immediate value +int32_t +ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const +{ + assert(shamt < 32); + ArmShiftType shiftType; + shiftType = (ArmShiftType)type; + + switch (shiftType) + { + case LSL: + return base << shamt; + case LSR: + if (shamt == 0) + return 0; + else + return base >> shamt; + case ASR: + if (shamt == 0) + return (base >> 31) | -((base & (1 << 31)) >> 31); + else + return (base >> shamt) | -((base & (1 << 31)) >> shamt); + case ROR: + if (shamt == 0) + return (cfval << 31) | (base >> 1); // RRX + else + return (base << (32 - shamt)) | (base >> shamt); + default: + ccprintf(std::cerr, "Unhandled shift type\n"); + exit(1); + break; + } + return 0; +} + +// Shift Rm by Rs +int32_t +ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const +{ + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + switch (shiftType) + { + case LSL: + if (shamt >= 32) + return 0; + else + return base << shamt; + case LSR: + if (shamt >= 32) + return 0; + else + return base >> shamt; + case ASR: + if (shamt >= 32) + return (base >> 31) | -((base & (1 << 31)) >> 31); + else + return (base >> shamt) | -((base & (1 << 31)) >> shamt); + case ROR: + shamt = shamt & 0x1f; + if (shamt == 0) + return base; + else + return (base << (32 - shamt)) | (base >> shamt); + default: + ccprintf(std::cerr, "Unhandled shift type\n"); + exit(1); + break; + } + return 0; +} + + +// Generate C for a shift by immediate +bool +ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const +{ + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + switch (shiftType) + { + case LSL: + if (shamt == 0) + return cfval; + else + return (base >> (32 - shamt)) & 1; + case LSR: + if (shamt == 0) + return (base >> 31); + else + return (base >> (shamt - 1)) & 1; + case ASR: + if (shamt == 0) + return (base >> 31); + else + return (base >> (shamt - 1)) & 1; + case ROR: + shamt = shamt & 0x1f; + if (shamt == 0) + return (base & 1); // RRX + else + return (base >> (shamt - 1)) & 1; + default: + ccprintf(std::cerr, "Unhandled shift type\n"); + exit(1); + break; + } + return 0; +} + + +// Generate C for a shift by Rs +bool +ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const +{ + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + if (shamt == 0) + return cfval; + + switch (shiftType) + { + case LSL: + if (shamt > 32) + return 0; + else + return (base >> (32 - shamt)) & 1; + case LSR: + if (shamt > 32) + return 0; + else + return (base >> (shamt - 1)) & 1; + case ASR: + if (shamt > 32) + shamt = 32; + return (base >> (shamt - 1)) & 1; + case ROR: + shamt = shamt & 0x1f; + if (shamt == 0) + shamt = 32; + return (base >> (shamt - 1)) & 1; + default: + ccprintf(std::cerr, "Unhandled shift type\n"); + exit(1); + break; + } + return 0; +} + + +void +ArmStaticInst::printReg(std::ostream &os, int reg) const +{ + if (reg < FP_Base_DepTag) { + switch (reg) { + case PCReg: + ccprintf(os, "pc"); + break; + case StackPointerReg: + ccprintf(os, "sp"); + break; + case FramePointerReg: + ccprintf(os, "fp"); + break; + case ReturnAddressReg: + ccprintf(os, "lr"); + break; + default: + ccprintf(os, "r%d", reg); + break; + } + } else if (reg < Ctrl_Base_DepTag) { + ccprintf(os, "f%d", reg - FP_Base_DepTag); + } else { + reg -= Ctrl_Base_DepTag; + assert(reg < NUM_MISCREGS); + ccprintf(os, "%s", ArmISA::miscRegName[reg]); + } +} + +void +ArmStaticInst::printMnemonic(std::ostream &os, + const std::string &suffix, + bool withPred) const +{ + os << " " << mnemonic; + if (withPred) { + unsigned condCode = machInst.condCode; + switch (condCode) { + case COND_EQ: + os << "eq"; + break; + case COND_NE: + os << "ne"; + break; + case COND_CS: + os << "cs"; + break; + case COND_CC: + os << "cc"; + break; + case COND_MI: + os << "mi"; + break; + case COND_PL: + os << "pl"; + break; + case COND_VS: + os << "vs"; + break; + case COND_VC: + os << "vc"; + break; + case COND_HI: + os << "hi"; + break; + case COND_LS: + os << "ls"; + break; + case COND_GE: + os << "ge"; + break; + case COND_LT: + os << "lt"; + break; + case COND_GT: + os << "gt"; + break; + case COND_LE: + os << "le"; + break; + case COND_AL: + // This one is implicit. + break; + case COND_UC: + // Unconditional. + break; + default: + panic("Unrecognized condition code %d.\n", condCode); + } + os << suffix; + if (machInst.bigThumb) + os << ".w"; + os << " "; + } +} + +void +ArmStaticInst::printMemSymbol(std::ostream &os, + const SymbolTable *symtab, + const std::string &prefix, + const Addr addr, + const std::string &suffix) const +{ + Addr symbolAddr; + std::string symbol; + if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { + ccprintf(os, "%s%s", prefix, symbol); + if (symbolAddr != addr) + ccprintf(os, "+%d", addr - symbolAddr); + ccprintf(os, suffix); + } +} + +void +ArmStaticInst::printShiftOperand(std::ostream &os, + IntRegIndex rm, + bool immShift, + uint32_t shiftAmt, + IntRegIndex rs, + ArmShiftType type) const +{ + bool firstOp = false; + + if (rm != INTREG_ZERO) { + printReg(os, rm); + } + + bool done = false; + + if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) + shiftAmt = 32; + + switch (type) { + case LSL: + if (immShift && shiftAmt == 0) { + done = true; + break; + } + if (!firstOp) + os << ", "; + os << "LSL"; + break; + case LSR: + if (!firstOp) + os << ", "; + os << "LSR"; + break; + case ASR: + if (!firstOp) + os << ", "; + os << "ASR"; + break; + case ROR: + if (immShift && shiftAmt == 0) { + if (!firstOp) + os << ", "; + os << "RRX"; + done = true; + break; + } + if (!firstOp) + os << ", "; + os << "ROR"; + break; + default: + panic("Tried to disassemble unrecognized shift type.\n"); + } + if (!done) { + if (!firstOp) + os << " "; + if (immShift) + os << "#" << shiftAmt; + else + printReg(os, rs); + } +} + +void +ArmStaticInst::printDataInst(std::ostream &os, bool withImm, + bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, + IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, + ArmShiftType type, uint32_t imm) const +{ + printMnemonic(os, s ? "s" : ""); + bool firstOp = true; + + // Destination + if (rd != INTREG_ZERO) { + firstOp = false; + printReg(os, rd); + } + + // Source 1. + if (rn != INTREG_ZERO) { + if (!firstOp) + os << ", "; + firstOp = false; + printReg(os, rn); + } + + if (!firstOp) + os << ", "; + if (withImm) { + ccprintf(os, "#%d", imm); + } else { + printShiftOperand(os, rm, immShift, shiftAmt, rs, type); + } +} + +std::string +ArmStaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + return ss.str(); +} +} diff --git a/simulators/gem5/src/arch/arm/insts/static_inst.hh b/simulators/gem5/src/arch/arm/insts/static_inst.hh new file mode 100644 index 00000000..c36024ec --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/static_inst.hh @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + */ +#ifndef __ARCH_ARM_INSTS_STATICINST_HH__ +#define __ARCH_ARM_INSTS_STATICINST_HH__ + +#include "arch/arm/faults.hh" +#include "arch/arm/utility.hh" +#include "base/trace.hh" +#include "cpu/static_inst.hh" +#include "sim/byteswap.hh" +#include "sim/full_system.hh" + +namespace ArmISA +{ + +class ArmStaticInst : public StaticInst +{ + protected: + int32_t shift_rm_imm(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const; + int32_t shift_rm_rs(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const; + + bool shift_carry_imm(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const; + bool shift_carry_rs(uint32_t base, uint32_t shamt, + uint32_t type, uint32_t cfval) const; + + template + static inline bool + saturateOp(int32_t &res, int64_t op1, int64_t op2, bool sub=false) + { + int64_t midRes = sub ? (op1 - op2) : (op1 + op2); + if (bits(midRes, width) != bits(midRes, width - 1)) { + if (midRes > 0) + res = (LL(1) << (width - 1)) - 1; + else + res = -(LL(1) << (width - 1)); + return true; + } else { + res = midRes; + return false; + } + } + + static inline bool + satInt(int32_t &res, int64_t op, int width) + { + width--; + if (op >= (LL(1) << width)) { + res = (LL(1) << width) - 1; + return true; + } else if (op < -(LL(1) << width)) { + res = -(LL(1) << width); + return true; + } else { + res = op; + return false; + } + } + + template + static inline bool + uSaturateOp(uint32_t &res, int64_t op1, int64_t op2, bool sub=false) + { + int64_t midRes = sub ? (op1 - op2) : (op1 + op2); + if (midRes >= (LL(1) << width)) { + res = (LL(1) << width) - 1; + return true; + } else if (midRes < 0) { + res = 0; + return true; + } else { + res = midRes; + return false; + } + } + + static inline bool + uSatInt(int32_t &res, int64_t op, int width) + { + if (op >= (LL(1) << width)) { + res = (LL(1) << width) - 1; + return true; + } else if (op < 0) { + res = 0; + return true; + } else { + res = op; + return false; + } + } + + // Constructor + ArmStaticInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + /// Print a register name for disassembly given the unique + /// dependence tag number (FP or int). + void printReg(std::ostream &os, int reg) const; + void printMnemonic(std::ostream &os, + const std::string &suffix = "", + bool withPred = true) const; + void printMemSymbol(std::ostream &os, const SymbolTable *symtab, + const std::string &prefix, const Addr addr, + const std::string &suffix) const; + void printShiftOperand(std::ostream &os, IntRegIndex rm, + bool immShift, uint32_t shiftAmt, + IntRegIndex rs, ArmShiftType type) const; + + + void printDataInst(std::ostream &os, bool withImm) const; + void printDataInst(std::ostream &os, bool withImm, bool immShift, bool s, + IntRegIndex rd, IntRegIndex rn, IntRegIndex rm, + IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type, + uint32_t imm) const; + + void + advancePC(PCState &pcState) const + { + pcState.advance(); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + static inline uint32_t + cpsrWriteByInstr(CPSR cpsr, uint32_t val, + uint8_t byteMask, bool affectState, bool nmfi) + { + bool privileged = (cpsr.mode != MODE_USER); + + uint32_t bitMask = 0; + + if (bits(byteMask, 3)) { + unsigned lowIdx = affectState ? 24 : 27; + bitMask = bitMask | mask(31, lowIdx); + } + if (bits(byteMask, 2)) { + bitMask = bitMask | mask(19, 16); + } + if (bits(byteMask, 1)) { + unsigned highIdx = affectState ? 15 : 9; + unsigned lowIdx = privileged ? 8 : 9; + bitMask = bitMask | mask(highIdx, lowIdx); + } + if (bits(byteMask, 0)) { + if (privileged) { + bitMask = bitMask | mask(7, 6); + if (!badMode((OperatingMode)(val & mask(5)))) { + bitMask = bitMask | mask(5); + } else { + warn_once("Ignoring write of bad mode to CPSR.\n"); + } + } + if (affectState) + bitMask = bitMask | (1 << 5); + } + + bool cpsr_f = cpsr.f; + uint32_t new_cpsr = ((uint32_t)cpsr & ~bitMask) | (val & bitMask); + if (nmfi && !cpsr_f) + new_cpsr &= ~(1 << 6); + return new_cpsr; + } + + static inline uint32_t + spsrWriteByInstr(uint32_t spsr, uint32_t val, + uint8_t byteMask, bool affectState) + { + uint32_t bitMask = 0; + + if (bits(byteMask, 3)) + bitMask = bitMask | mask(31, 24); + if (bits(byteMask, 2)) + bitMask = bitMask | mask(19, 16); + if (bits(byteMask, 1)) + bitMask = bitMask | mask(15, 8); + if (bits(byteMask, 0)) + bitMask = bitMask | mask(7, 0); + + return ((spsr & ~bitMask) | (val & bitMask)); + } + + template + static inline Addr + readPC(XC *xc) + { + return xc->pcState().instPC(); + } + + template + static inline void + setNextPC(XC *xc, Addr val) + { + PCState pc = xc->pcState(); + pc.instNPC(val); + xc->pcState(pc); + } + + template + static inline T + cSwap(T val, bool big) + { + if (big) { + return gtobe(val); + } else { + return gtole(val); + } + } + + template + static inline T + cSwap(T val, bool big) + { + const unsigned count = sizeof(T) / sizeof(E); + union { + T tVal; + E eVals[count]; + } conv; + conv.tVal = htog(val); + if (big) { + for (unsigned i = 0; i < count; i++) { + conv.eVals[i] = gtobe(conv.eVals[i]); + } + } else { + for (unsigned i = 0; i < count; i++) { + conv.eVals[i] = gtole(conv.eVals[i]); + } + } + return gtoh(conv.tVal); + } + + // Perform an interworking branch. + template + static inline void + setIWNextPC(XC *xc, Addr val) + { + PCState pc = xc->pcState(); + pc.instIWNPC(val); + xc->pcState(pc); + } + + // Perform an interworking branch in ARM mode, a regular branch + // otherwise. + template + static inline void + setAIWNextPC(XC *xc, Addr val) + { + PCState pc = xc->pcState(); + pc.instAIWNPC(val); + xc->pcState(pc); + } + + inline Fault + disabledFault() const + { + if (FullSystem) { + return new UndefinedInstruction(); + } else { + return new UndefinedInstruction(machInst, false, mnemonic, true); + } + } +}; +} + +#endif //__ARCH_ARM_INSTS_STATICINST_HH__ diff --git a/simulators/gem5/src/arch/arm/insts/vfp.cc b/simulators/gem5/src/arch/arm/insts/vfp.cc new file mode 100644 index 00000000..f689204d --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/vfp.cc @@ -0,0 +1,1156 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/arm/insts/vfp.hh" + +/* + * The asm statements below are to keep gcc from reordering code. Otherwise + * the rounding mode might be set after the operation it was intended for, the + * exception bits read before it, etc. + */ + +std::string +FpRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + return ss.str(); +} + +std::string +FpRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +FpRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + ss << ", "; + printReg(ss, op2 + FP_Base_DepTag); + return ss.str(); +} + +std::string +FpRegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + ss << ", "; + printReg(ss, op2 + FP_Base_DepTag); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +namespace ArmISA +{ + +VfpSavedState +prepFpState(uint32_t rMode) +{ + int roundingMode = fegetround(); + feclearexcept(FeAllExceptions); + switch (rMode) { + case VfpRoundNearest: + fesetround(FeRoundNearest); + break; + case VfpRoundUpward: + fesetround(FeRoundUpward); + break; + case VfpRoundDown: + fesetround(FeRoundDown); + break; + case VfpRoundZero: + fesetround(FeRoundZero); + break; + } + return roundingMode; +} + +void +finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush) +{ + int exceptions = fetestexcept(FeAllExceptions); + bool underflow = false; + if (exceptions & FeInvalid) { + fpscr.ioc = 1; + } + if (exceptions & FeDivByZero) { + fpscr.dzc = 1; + } + if (exceptions & FeOverflow) { + fpscr.ofc = 1; + } + if (exceptions & FeUnderflow) { + underflow = true; + fpscr.ufc = 1; + } + if ((exceptions & FeInexact) && !(underflow && flush)) { + fpscr.ixc = 1; + } + fesetround(state); +} + +template +fpType +fixDest(bool flush, bool defaultNan, fpType val, fpType op1) +{ + int fpClass = std::fpclassify(val); + fpType junk = 0.0; + if (fpClass == FP_NAN) { + const bool single = (sizeof(val) == sizeof(float)); + const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan = std::isnan(op1); + if (!nan || defaultNan) { + val = bitsToFp(qnan, junk); + } else if (nan) { + val = bitsToFp(fpToBits(op1) | qnan, junk); + } + } else if (fpClass == FP_SUBNORMAL && flush == 1) { + // Turn val into a zero with the correct sign; + uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); + val = bitsToFp(fpToBits(val) & bitMask, junk); + feclearexcept(FeInexact); + feraiseexcept(FeUnderflow); + } + return val; +} + +template +float fixDest(bool flush, bool defaultNan, float val, float op1); +template +double fixDest(bool flush, bool defaultNan, double val, double op1); + +template +fpType +fixDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2) +{ + int fpClass = std::fpclassify(val); + fpType junk = 0.0; + if (fpClass == FP_NAN) { + const bool single = (sizeof(val) == sizeof(float)); + const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan1 = std::isnan(op1); + const bool nan2 = std::isnan(op2); + const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); + const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); + if ((!nan1 && !nan2) || defaultNan) { + val = bitsToFp(qnan, junk); + } else if (signal1) { + val = bitsToFp(fpToBits(op1) | qnan, junk); + } else if (signal2) { + val = bitsToFp(fpToBits(op2) | qnan, junk); + } else if (nan1) { + val = op1; + } else if (nan2) { + val = op2; + } + } else if (fpClass == FP_SUBNORMAL && flush) { + // Turn val into a zero with the correct sign; + uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); + val = bitsToFp(fpToBits(val) & bitMask, junk); + feclearexcept(FeInexact); + feraiseexcept(FeUnderflow); + } + return val; +} + +template +float fixDest(bool flush, bool defaultNan, + float val, float op1, float op2); +template +double fixDest(bool flush, bool defaultNan, + double val, double op1, double op2); + +template +fpType +fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2) +{ + fpType mid = fixDest(flush, defaultNan, val, op1, op2); + const bool single = (sizeof(fpType) == sizeof(float)); + const fpType junk = 0.0; + if ((single && (val == bitsToFp(0x00800000, junk) || + val == bitsToFp(0x80800000, junk))) || + (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || + val == bitsToFp(ULL(0x8010000000000000), junk))) + ) { + __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); + fesetround(FeRoundZero); + fpType temp = 0.0; + __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); + temp = op1 / op2; + if (flushToZero(temp)) { + feraiseexcept(FeUnderflow); + if (flush) { + feclearexcept(FeInexact); + mid = temp; + } + } + __asm__ __volatile__("" :: "m" (temp)); + } + return mid; +} + +template +float fixDivDest(bool flush, bool defaultNan, + float val, float op1, float op2); +template +double fixDivDest(bool flush, bool defaultNan, + double val, double op1, double op2); + +float +fixFpDFpSDest(FPSCR fpscr, double val) +{ + const float junk = 0.0; + float op1 = 0.0; + if (std::isnan(val)) { + uint64_t valBits = fpToBits(val); + uint32_t op1Bits = bits(valBits, 50, 29) | + (mask(9) << 22) | + (bits(valBits, 63) << 31); + op1 = bitsToFp(op1Bits, junk); + } + float mid = fixDest(fpscr.fz, fpscr.dn, (float)val, op1); + if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == + (FeUnderflow | FeInexact)) { + feclearexcept(FeInexact); + } + if (mid == bitsToFp(0x00800000, junk) || + mid == bitsToFp(0x80800000, junk)) { + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(FeRoundZero); + float temp = 0.0; + __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); + temp = val; + if (flushToZero(temp)) { + feraiseexcept(FeUnderflow); + if (fpscr.fz) { + feclearexcept(FeInexact); + mid = temp; + } + } + __asm__ __volatile__("" :: "m" (temp)); + } + return mid; +} + +double +fixFpSFpDDest(FPSCR fpscr, float val) +{ + const double junk = 0.0; + double op1 = 0.0; + if (std::isnan(val)) { + uint32_t valBits = fpToBits(val); + uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | + (mask(12) << 51) | + ((uint64_t)bits(valBits, 31) << 63); + op1 = bitsToFp(op1Bits, junk); + } + double mid = fixDest(fpscr.fz, fpscr.dn, (double)val, op1); + if (mid == bitsToFp(ULL(0x0010000000000000), junk) || + mid == bitsToFp(ULL(0x8010000000000000), junk)) { + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(FeRoundZero); + double temp = 0.0; + __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); + temp = val; + if (flushToZero(temp)) { + feraiseexcept(FeUnderflow); + if (fpscr.fz) { + feclearexcept(FeInexact); + mid = temp; + } + } + __asm__ __volatile__("" :: "m" (temp)); + } + return mid; +} + +uint16_t +vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, + uint32_t rMode, bool ahp, float op) +{ + uint32_t opBits = fpToBits(op); + // Extract the operand. + bool neg = bits(opBits, 31); + uint32_t exponent = bits(opBits, 30, 23); + uint32_t oldMantissa = bits(opBits, 22, 0); + uint32_t mantissa = oldMantissa >> (23 - 10); + // Do the conversion. + uint32_t extra = oldMantissa & mask(23 - 10); + if (exponent == 0xff) { + if (oldMantissa != 0) { + // Nans. + if (bits(mantissa, 9) == 0) { + // Signalling nan. + fpscr.ioc = 1; + } + if (ahp) { + mantissa = 0; + exponent = 0; + fpscr.ioc = 1; + } else if (defaultNan) { + mantissa = (1 << 9); + exponent = 0x1f; + neg = false; + } else { + exponent = 0x1f; + mantissa |= (1 << 9); + } + } else { + // Infinities. + exponent = 0x1F; + if (ahp) { + fpscr.ioc = 1; + mantissa = 0x3ff; + } else { + mantissa = 0; + } + } + } else if (exponent == 0 && oldMantissa == 0) { + // Zero, don't need to do anything. + } else { + // Normalized or denormalized numbers. + + bool inexact = (extra != 0); + + if (exponent == 0) { + // Denormalized. + + // If flush to zero is on, this shouldn't happen. + assert(!flush); + + // Check for underflow + if (inexact || fpscr.ufe) + fpscr.ufc = 1; + + // Handle rounding. + unsigned mode = rMode; + if ((mode == VfpRoundUpward && !neg && extra) || + (mode == VfpRoundDown && neg && extra) || + (mode == VfpRoundNearest && + (extra > (1 << 9) || + (extra == (1 << 9) && bits(mantissa, 0))))) { + mantissa++; + } + + // See if the number became normalized after rounding. + if (mantissa == (1 << 10)) { + mantissa = 0; + exponent = 1; + } + } else { + // Normalized. + + // We need to track the dropped bits differently since + // more can be dropped by denormalizing. + bool topOne = bits(extra, 12); + bool restZeros = bits(extra, 11, 0) == 0; + + if (exponent <= (127 - 15)) { + // The result is too small. Denormalize. + mantissa |= (1 << 10); + while (mantissa && exponent <= (127 - 15)) { + restZeros = restZeros && !topOne; + topOne = bits(mantissa, 0); + mantissa = mantissa >> 1; + exponent++; + } + if (topOne || !restZeros) + inexact = true; + exponent = 0; + } else { + // Change bias. + exponent -= (127 - 15); + } + + if (exponent == 0 && (inexact || fpscr.ufe)) { + // Underflow + fpscr.ufc = 1; + } + + // Handle rounding. + unsigned mode = rMode; + bool nonZero = topOne || !restZeros; + if ((mode == VfpRoundUpward && !neg && nonZero) || + (mode == VfpRoundDown && neg && nonZero) || + (mode == VfpRoundNearest && topOne && + (!restZeros || bits(mantissa, 0)))) { + mantissa++; + } + + // See if we rounded up and need to bump the exponent. + if (mantissa == (1 << 10)) { + mantissa = 0; + exponent++; + } + + // Deal with overflow + if (ahp) { + if (exponent >= 0x20) { + exponent = 0x1f; + mantissa = 0x3ff; + fpscr.ioc = 1; + // Supress inexact exception. + inexact = false; + } + } else { + if (exponent >= 0x1f) { + if ((mode == VfpRoundNearest) || + (mode == VfpRoundUpward && !neg) || + (mode == VfpRoundDown && neg)) { + // Overflow to infinity. + exponent = 0x1f; + mantissa = 0; + } else { + // Overflow to max normal. + exponent = 0x1e; + mantissa = 0x3ff; + } + fpscr.ofc = 1; + inexact = true; + } + } + } + + if (inexact) { + fpscr.ixc = 1; + } + } + // Reassemble and install the result. + uint32_t result = bits(mantissa, 9, 0); + replaceBits(result, 14, 10, exponent); + if (neg) + result |= (1 << 15); + return result; +} + +float +vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op) +{ + float junk = 0.0; + // Extract the bitfields. + bool neg = bits(op, 15); + uint32_t exponent = bits(op, 14, 10); + uint32_t mantissa = bits(op, 9, 0); + // Do the conversion. + if (exponent == 0) { + if (mantissa != 0) { + // Normalize the value. + exponent = exponent + (127 - 15) + 1; + while (mantissa < (1 << 10)) { + mantissa = mantissa << 1; + exponent--; + } + } + mantissa = mantissa << (23 - 10); + } else if (exponent == 0x1f && !ahp) { + // Infinities and nans. + exponent = 0xff; + if (mantissa != 0) { + // Nans. + mantissa = mantissa << (23 - 10); + if (bits(mantissa, 22) == 0) { + // Signalling nan. + fpscr.ioc = 1; + mantissa |= (1 << 22); + } + if (defaultNan) { + mantissa &= ~mask(22); + neg = false; + } + } + } else { + exponent = exponent + (127 - 15); + mantissa = mantissa << (23 - 10); + } + // Reassemble the result. + uint32_t result = bits(mantissa, 22, 0); + replaceBits(result, 30, 23, exponent); + if (neg) + result |= (1 << 31); + return bitsToFp(result, junk); +} + +uint64_t +vfpFpSToFixed(float val, bool isSigned, bool half, + uint8_t imm, bool rzero) +{ + int rmode = rzero ? FeRoundZero : fegetround(); + __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); + fesetround(FeRoundNearest); + val = val * powf(2.0, imm); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(rmode); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + float origVal = val; + val = rintf(val); + int fpType = std::fpclassify(val); + if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { + if (fpType == FP_NAN) { + feraiseexcept(FeInvalid); + } + val = 0.0; + } else if (origVal != val) { + switch (rmode) { + case FeRoundNearest: + if (origVal - val > 0.5) + val += 1.0; + else if (val - origVal > 0.5) + val -= 1.0; + break; + case FeRoundDown: + if (origVal < val) + val -= 1.0; + break; + case FeRoundUpward: + if (origVal > val) + val += 1.0; + break; + } + feraiseexcept(FeInexact); + } + + if (isSigned) { + if (half) { + if ((double)val < (int16_t)(1 << 15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)(1 << 15); + } + if ((double)val > (int16_t)mask(15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)mask(15); + } + return (int16_t)val; + } else { + if ((double)val < (int32_t)(1 << 31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)(1 << 31); + } + if ((double)val > (int32_t)mask(31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)mask(31); + } + return (int32_t)val; + } + } else { + if (half) { + if ((double)val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if ((double)val > (mask(16))) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(16); + } + return (uint16_t)val; + } else { + if ((double)val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if ((double)val > (mask(32))) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(32); + } + return (uint32_t)val; + } + } +} + +float +vfpUFixedToFpS(bool flush, bool defaultNan, + uint32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = (uint16_t)val; + float scale = powf(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(flush, defaultNan, val / scale, (float)val, scale); +} + +float +vfpSFixedToFpS(bool flush, bool defaultNan, + int32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = sext<16>(val & mask(16)); + float scale = powf(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(flush, defaultNan, val / scale, (float)val, scale); +} + +uint64_t +vfpFpDToFixed(double val, bool isSigned, bool half, + uint8_t imm, bool rzero) +{ + int rmode = rzero ? FeRoundZero : fegetround(); + fesetround(FeRoundNearest); + val = val * pow(2.0, imm); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(rmode); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + double origVal = val; + val = rint(val); + int fpType = std::fpclassify(val); + if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { + if (fpType == FP_NAN) { + feraiseexcept(FeInvalid); + } + val = 0.0; + } else if (origVal != val) { + switch (rmode) { + case FeRoundNearest: + if (origVal - val > 0.5) + val += 1.0; + else if (val - origVal > 0.5) + val -= 1.0; + break; + case FeRoundDown: + if (origVal < val) + val -= 1.0; + break; + case FeRoundUpward: + if (origVal > val) + val += 1.0; + break; + } + feraiseexcept(FeInexact); + } + if (isSigned) { + if (half) { + if (val < (int16_t)(1 << 15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)(1 << 15); + } + if (val > (int16_t)mask(15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)mask(15); + } + return (int16_t)val; + } else { + if (val < (int32_t)(1 << 31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)(1 << 31); + } + if (val > (int32_t)mask(31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)mask(31); + } + return (int32_t)val; + } + } else { + if (half) { + if (val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if (val > mask(16)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(16); + } + return (uint16_t)val; + } else { + if (val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if (val > mask(32)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(32); + } + return (uint32_t)val; + } + } +} + +double +vfpUFixedToFpD(bool flush, bool defaultNan, + uint32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = (uint16_t)val; + double scale = pow(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(flush, defaultNan, val / scale, (double)val, scale); +} + +double +vfpSFixedToFpD(bool flush, bool defaultNan, + int32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = sext<16>(val & mask(16)); + double scale = pow(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(flush, defaultNan, val / scale, (double)val, scale); +} + +// This function implements a magic formula taken from the architecture +// reference manual. It was originally called recip_sqrt_estimate. +static double +recipSqrtEstimate(double a) +{ + int64_t q0, q1, s; + double r; + if (a < 0.5) { + q0 = (int64_t)(a * 512.0); + r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0); + } else { + q1 = (int64_t)(a * 256.0); + r = 1.0 / sqrt(((double)q1 + 0.5) / 256.0); + } + s = (int64_t)(256.0 * r + 0.5); + return (double)s / 256.0; +} + +// This function is only intended for use in Neon instructions because +// it ignores certain bits in the FPSCR. +float +fprSqrtEstimate(FPSCR &fpscr, float op) +{ + const uint32_t qnan = 0x7fc00000; + float junk = 0.0; + int fpClass = std::fpclassify(op); + if (fpClass == FP_NAN) { + if ((fpToBits(op) & qnan) != qnan) + fpscr.ioc = 1; + return bitsToFp(qnan, junk); + } else if (fpClass == FP_ZERO) { + fpscr.dzc = 1; + // Return infinity with the same sign as the operand. + return bitsToFp((std::signbit(op) << 31) | + (0xFF << 23) | (0 << 0), junk); + } else if (std::signbit(op)) { + // Set invalid op bit. + fpscr.ioc = 1; + return bitsToFp(qnan, junk); + } else if (fpClass == FP_INFINITE) { + return 0.0; + } else { + uint64_t opBits = fpToBits(op); + double scaled; + if (bits(opBits, 23)) { + scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | + (ULL(0x3fd) << 52) | (bits(opBits, 31) << 63), + (double)0.0); + } else { + scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | + (ULL(0x3fe) << 52) | (bits(opBits, 31) << 63), + (double)0.0); + } + uint64_t resultExp = (380 - bits(opBits, 30, 23)) / 2; + + uint64_t estimate = fpToBits(recipSqrtEstimate(scaled)); + + return bitsToFp((bits(estimate, 63) << 31) | + (bits(resultExp, 7, 0) << 23) | + (bits(estimate, 51, 29) << 0), junk); + } +} + +uint32_t +unsignedRSqrtEstimate(uint32_t op) +{ + if (bits(op, 31, 30) == 0) { + return -1; + } else { + double dpOp; + if (bits(op, 31)) { + dpOp = bitsToFp((ULL(0) << 63) | + (ULL(0x3fe) << 52) | + (bits((uint64_t)op, 30, 0) << 21) | + (0 << 0), (double)0.0); + } else { + dpOp = bitsToFp((ULL(0) << 63) | + (ULL(0x3fd) << 52) | + (bits((uint64_t)op, 29, 0) << 22) | + (0 << 0), (double)0.0); + } + uint64_t estimate = fpToBits(recipSqrtEstimate(dpOp)); + return (1 << 31) | bits(estimate, 51, 21); + } +} + +// This function implements a magic formula taken from the architecture +// reference manual. It was originally called recip_estimate. + +static double +recipEstimate(double a) +{ + int64_t q, s; + double r; + q = (int64_t)(a * 512.0); + r = 1.0 / (((double)q + 0.5) / 512.0); + s = (int64_t)(256.0 * r + 0.5); + return (double)s / 256.0; +} + +// This function is only intended for use in Neon instructions because +// it ignores certain bits in the FPSCR. +float +fpRecipEstimate(FPSCR &fpscr, float op) +{ + const uint32_t qnan = 0x7fc00000; + float junk = 0.0; + int fpClass = std::fpclassify(op); + if (fpClass == FP_NAN) { + if ((fpToBits(op) & qnan) != qnan) + fpscr.ioc = 1; + return bitsToFp(qnan, junk); + } else if (fpClass == FP_INFINITE) { + return bitsToFp(std::signbit(op) << 31, junk); + } else if (fpClass == FP_ZERO) { + fpscr.dzc = 1; + // Return infinity with the same sign as the operand. + return bitsToFp((std::signbit(op) << 31) | + (0xFF << 23) | (0 << 0), junk); + } else if (fabs(op) >= pow(2.0, 126)) { + fpscr.ufc = 1; + return bitsToFp(std::signbit(op) << 31, junk); + } else { + uint64_t opBits = fpToBits(op); + double scaled; + scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | + (ULL(0x3fe) << 52) | (ULL(0) << 63), + (double)0.0); + uint64_t resultExp = 253 - bits(opBits, 30, 23); + + uint64_t estimate = fpToBits(recipEstimate(scaled)); + + return bitsToFp((bits(opBits, 31) << 31) | + (bits(resultExp, 7, 0) << 23) | + (bits(estimate, 51, 29) << 0), junk); + } +} + +uint32_t +unsignedRecipEstimate(uint32_t op) +{ + if (bits(op, 31) == 0) { + return -1; + } else { + double dpOp; + dpOp = bitsToFp((ULL(0) << 63) | + (ULL(0x3fe) << 52) | + (bits((uint64_t)op, 30, 0) << 21) | + (0 << 0), (double)0.0); + uint64_t estimate = fpToBits(recipEstimate(dpOp)); + return (1 << 31) | bits(estimate, 51, 21); + } +} + +template +fpType +FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, + fpType op1, fpType op2) const +{ + done = true; + fpType junk = 0.0; + fpType dest = 0.0; + const bool single = (sizeof(fpType) == sizeof(float)); + const uint64_t qnan = + single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan1 = std::isnan(op1); + const bool nan2 = std::isnan(op2); + const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); + const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); + if (nan1 || nan2) { + if (defaultNan) { + dest = bitsToFp(qnan, junk); + } else if (signal1) { + dest = bitsToFp(fpToBits(op1) | qnan, junk); + } else if (signal2) { + dest = bitsToFp(fpToBits(op2) | qnan, junk); + } else if (nan1) { + dest = op1; + } else if (nan2) { + dest = op2; + } + if (signal1 || signal2) { + fpscr.ioc = 1; + } + } else { + done = false; + } + return dest; +} + +template +float FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, + float op1, float op2) const; +template +double FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, + double op1, double op2) const; + +template +fpType +FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, + fpType (*func)(fpType, fpType), + bool flush, bool defaultNan, uint32_t rMode) const +{ + const bool single = (sizeof(fpType) == sizeof(float)); + fpType junk = 0.0; + + if (flush && flushToZero(op1, op2)) + fpscr.idc = 1; + VfpSavedState state = prepFpState(rMode); + __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) + : "m" (op1), "m" (op2), "m" (state)); + fpType dest = func(op1, op2); + __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); + + int fpClass = std::fpclassify(dest); + // Get NAN behavior right. This varies between x86 and ARM. + if (fpClass == FP_NAN) { + const bool single = (sizeof(fpType) == sizeof(float)); + const uint64_t qnan = + single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan1 = std::isnan(op1); + const bool nan2 = std::isnan(op2); + const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); + const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); + if ((!nan1 && !nan2) || (defaultNan == 1)) { + dest = bitsToFp(qnan, junk); + } else if (signal1) { + dest = bitsToFp(fpToBits(op1) | qnan, junk); + } else if (signal2) { + dest = bitsToFp(fpToBits(op2) | qnan, junk); + } else if (nan1) { + dest = op1; + } else if (nan2) { + dest = op2; + } + } else if (flush && flushToZero(dest)) { + feraiseexcept(FeUnderflow); + } else if (( + (single && (dest == bitsToFp(0x00800000, junk) || + dest == bitsToFp(0x80800000, junk))) || + (!single && + (dest == bitsToFp(ULL(0x0010000000000000), junk) || + dest == bitsToFp(ULL(0x8010000000000000), junk))) + ) && rMode != VfpRoundZero) { + /* + * Correct for the fact that underflow is detected -before- rounding + * in ARM and -after- rounding in x86. + */ + fesetround(FeRoundZero); + __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) + : "m" (op1), "m" (op2)); + fpType temp = func(op1, op2); + __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); + if (flush && flushToZero(temp)) { + dest = temp; + } + } + finishVfp(fpscr, state, flush); + return dest; +} + +template +float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, + float (*func)(float, float), + bool flush, bool defaultNan, uint32_t rMode) const; +template +double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, + double (*func)(double, double), + bool flush, bool defaultNan, uint32_t rMode) const; + +template +fpType +FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), + bool flush, uint32_t rMode) const +{ + const bool single = (sizeof(fpType) == sizeof(float)); + fpType junk = 0.0; + + if (flush && flushToZero(op1)) + fpscr.idc = 1; + VfpSavedState state = prepFpState(rMode); + __asm__ __volatile__ ("" : "=m" (op1), "=m" (state) + : "m" (op1), "m" (state)); + fpType dest = func(op1); + __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); + + int fpClass = std::fpclassify(dest); + // Get NAN behavior right. This varies between x86 and ARM. + if (fpClass == FP_NAN) { + const bool single = (sizeof(fpType) == sizeof(float)); + const uint64_t qnan = + single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan = std::isnan(op1); + if (!nan || fpscr.dn == 1) { + dest = bitsToFp(qnan, junk); + } else if (nan) { + dest = bitsToFp(fpToBits(op1) | qnan, junk); + } + } else if (flush && flushToZero(dest)) { + feraiseexcept(FeUnderflow); + } else if (( + (single && (dest == bitsToFp(0x00800000, junk) || + dest == bitsToFp(0x80800000, junk))) || + (!single && + (dest == bitsToFp(ULL(0x0010000000000000), junk) || + dest == bitsToFp(ULL(0x8010000000000000), junk))) + ) && rMode != VfpRoundZero) { + /* + * Correct for the fact that underflow is detected -before- rounding + * in ARM and -after- rounding in x86. + */ + fesetround(FeRoundZero); + __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); + fpType temp = func(op1); + __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); + if (flush && flushToZero(temp)) { + dest = temp; + } + } + finishVfp(fpscr, state, flush); + return dest; +} + +template +float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float), + bool flush, uint32_t rMode) const; +template +double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double), + bool flush, uint32_t rMode) const; + +IntRegIndex +VfpMacroOp::addStride(IntRegIndex idx, unsigned stride) +{ + if (wide) { + stride *= 2; + } + unsigned offset = idx % 8; + idx = (IntRegIndex)(idx - offset); + offset += stride; + idx = (IntRegIndex)(idx + (offset % 8)); + return idx; +} + +void +VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) +{ + unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; + assert(!inScalarBank(dest)); + dest = addStride(dest, stride); + op1 = addStride(op1, stride); + if (!inScalarBank(op2)) { + op2 = addStride(op2, stride); + } +} + +void +VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1) +{ + unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; + assert(!inScalarBank(dest)); + dest = addStride(dest, stride); + if (!inScalarBank(op1)) { + op1 = addStride(op1, stride); + } +} + +void +VfpMacroOp::nextIdxs(IntRegIndex &dest) +{ + unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; + assert(!inScalarBank(dest)); + dest = addStride(dest, stride); +} + +} diff --git a/simulators/gem5/src/arch/arm/insts/vfp.hh b/simulators/gem5/src/arch/arm/insts/vfp.hh new file mode 100644 index 00000000..9babaae0 --- /dev/null +++ b/simulators/gem5/src/arch/arm/insts/vfp.hh @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ARM_INSTS_VFP_HH__ +#define __ARCH_ARM_INSTS_VFP_HH__ + +#include + +#include + +#include "arch/arm/insts/misc.hh" +#include "arch/arm/miscregs.hh" + +namespace ArmISA +{ + +enum VfpMicroMode { + VfpNotAMicroop, + VfpMicroop, + VfpFirstMicroop, + VfpLastMicroop +}; + +template +static inline void +setVfpMicroFlags(VfpMicroMode mode, T &flags) +{ + switch (mode) { + case VfpMicroop: + flags[StaticInst::IsMicroop] = true; + break; + case VfpFirstMicroop: + flags[StaticInst::IsMicroop] = + flags[StaticInst::IsFirstMicroop] = true; + break; + case VfpLastMicroop: + flags[StaticInst::IsMicroop] = + flags[StaticInst::IsLastMicroop] = true; + break; + case VfpNotAMicroop: + break; + } + if (mode == VfpMicroop || mode == VfpFirstMicroop) { + flags[StaticInst::IsDelayedCommit] = true; + } +} + +enum FeExceptionBit +{ + FeDivByZero = FE_DIVBYZERO, + FeInexact = FE_INEXACT, + FeInvalid = FE_INVALID, + FeOverflow = FE_OVERFLOW, + FeUnderflow = FE_UNDERFLOW, + FeAllExceptions = FE_ALL_EXCEPT +}; + +enum FeRoundingMode +{ + FeRoundDown = FE_DOWNWARD, + FeRoundNearest = FE_TONEAREST, + FeRoundZero = FE_TOWARDZERO, + FeRoundUpward = FE_UPWARD +}; + +enum VfpRoundingMode +{ + VfpRoundNearest = 0, + VfpRoundUpward = 1, + VfpRoundDown = 2, + VfpRoundZero = 3 +}; + +static inline float bitsToFp(uint64_t, float); +static inline double bitsToFp(uint64_t, double); +static inline uint32_t fpToBits(float); +static inline uint64_t fpToBits(double); + +template +static inline bool +flushToZero(fpType &op) +{ + fpType junk = 0.0; + if (std::fpclassify(op) == FP_SUBNORMAL) { + uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); + op = bitsToFp(fpToBits(op) & bitMask, junk); + return true; + } + return false; +} + +template +static inline bool +flushToZero(fpType &op1, fpType &op2) +{ + bool flush1 = flushToZero(op1); + bool flush2 = flushToZero(op2); + return flush1 || flush2; +} + +template +static inline void +vfpFlushToZero(FPSCR &fpscr, fpType &op) +{ + if (fpscr.fz == 1 && flushToZero(op)) { + fpscr.idc = 1; + } +} + +template +static inline void +vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) +{ + vfpFlushToZero(fpscr, op1); + vfpFlushToZero(fpscr, op2); +} + +static inline uint32_t +fpToBits(float fp) +{ + union + { + float fp; + uint32_t bits; + } val; + val.fp = fp; + return val.bits; +} + +static inline uint64_t +fpToBits(double fp) +{ + union + { + double fp; + uint64_t bits; + } val; + val.fp = fp; + return val.bits; +} + +static inline float +bitsToFp(uint64_t bits, float junk) +{ + union + { + float fp; + uint32_t bits; + } val; + val.bits = bits; + return val.fp; +} + +static inline double +bitsToFp(uint64_t bits, double junk) +{ + union + { + double fp; + uint64_t bits; + } val; + val.bits = bits; + return val.fp; +} + +template +static bool +isSnan(fpType val) +{ + const bool single = (sizeof(fpType) == sizeof(float)); + const uint64_t qnan = + single ? 0x7fc00000 : ULL(0x7ff8000000000000); + return std::isnan(val) && ((fpToBits(val) & qnan) != qnan); +} + +typedef int VfpSavedState; + +VfpSavedState prepFpState(uint32_t rMode); +void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush); + +template +fpType fixDest(FPSCR fpscr, fpType val, fpType op1); + +template +fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); + +template +fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); + +float fixFpDFpSDest(FPSCR fpscr, double val); +double fixFpSFpDDest(FPSCR fpscr, float val); + +uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, + uint32_t rMode, bool ahp, float op); +float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op); + +static inline double +makeDouble(uint32_t low, uint32_t high) +{ + double junk = 0.0; + return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); +} + +static inline uint32_t +lowFromDouble(double val) +{ + return fpToBits(val); +} + +static inline uint32_t +highFromDouble(double val) +{ + return fpToBits(val) >> 32; +} + +uint64_t vfpFpSToFixed(float val, bool isSigned, bool half, + uint8_t imm, bool rzero = true); +float vfpUFixedToFpS(bool flush, bool defaultNan, + uint32_t val, bool half, uint8_t imm); +float vfpSFixedToFpS(bool flush, bool defaultNan, + int32_t val, bool half, uint8_t imm); + +uint64_t vfpFpDToFixed(double val, bool isSigned, bool half, + uint8_t imm, bool rzero = true); +double vfpUFixedToFpD(bool flush, bool defaultNan, + uint32_t val, bool half, uint8_t imm); +double vfpSFixedToFpD(bool flush, bool defaultNan, + int32_t val, bool half, uint8_t imm); + +float fprSqrtEstimate(FPSCR &fpscr, float op); +uint32_t unsignedRSqrtEstimate(uint32_t op); + +float fpRecipEstimate(FPSCR &fpscr, float op); +uint32_t unsignedRecipEstimate(uint32_t op); + +class VfpMacroOp : public PredMacroOp +{ + public: + static bool + inScalarBank(IntRegIndex idx) + { + return (idx % 32) < 8; + } + + protected: + bool wide; + + VfpMacroOp(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, bool _wide) : + PredMacroOp(mnem, _machInst, __opClass), wide(_wide) + {} + + IntRegIndex addStride(IntRegIndex idx, unsigned stride); + void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); + void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); + void nextIdxs(IntRegIndex &dest); +}; + +static inline float +fpAddS(float a, float b) +{ + return a + b; +} + +static inline double +fpAddD(double a, double b) +{ + return a + b; +} + +static inline float +fpSubS(float a, float b) +{ + return a - b; +} + +static inline double +fpSubD(double a, double b) +{ + return a - b; +} + +static inline float +fpDivS(float a, float b) +{ + return a / b; +} + +static inline double +fpDivD(double a, double b) +{ + return a / b; +} + +static inline float +fpMulS(float a, float b) +{ + return a * b; +} + +static inline double +fpMulD(double a, double b) +{ + return a * b; +} + +static inline float +fpMaxS(float a, float b) +{ + // Handle comparisons of +0 and -0. + if (!std::signbit(a) && std::signbit(b)) + return a; + return fmaxf(a, b); +} + +static inline float +fpMinS(float a, float b) +{ + // Handle comparisons of +0 and -0. + if (std::signbit(a) && !std::signbit(b)) + return a; + return fminf(a, b); +} + +static inline float +fpRSqrtsS(float a, float b) +{ + int fpClassA = std::fpclassify(a); + int fpClassB = std::fpclassify(b); + float aXb; + int fpClassAxB; + + if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || + (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { + return 1.5; + } + aXb = a*b; + fpClassAxB = std::fpclassify(aXb); + if(fpClassAxB == FP_SUBNORMAL) { + feraiseexcept(FeUnderflow); + return 1.5; + } + return (3.0 - (a * b)) / 2.0; +} + +static inline float +fpRecpsS(float a, float b) +{ + int fpClassA = std::fpclassify(a); + int fpClassB = std::fpclassify(b); + float aXb; + int fpClassAxB; + + if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || + (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { + return 2.0; + } + aXb = a*b; + fpClassAxB = std::fpclassify(aXb); + if(fpClassAxB == FP_SUBNORMAL) { + feraiseexcept(FeUnderflow); + return 2.0; + } + return 2.0 - (a * b); +} + +class FpOp : public PredOp +{ + protected: + FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + {} + + virtual float + doOp(float op1, float op2) const + { + panic("Unimplemented version of doOp called.\n"); + } + + virtual float + doOp(float op1) const + { + panic("Unimplemented version of doOp called.\n"); + } + + virtual double + doOp(double op1, double op2) const + { + panic("Unimplemented version of doOp called.\n"); + } + + virtual double + doOp(double op1) const + { + panic("Unimplemented version of doOp called.\n"); + } + + double + dbl(uint32_t low, uint32_t high) const + { + double junk = 0.0; + return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); + } + + uint32_t + dblLow(double val) const + { + return fpToBits(val); + } + + uint32_t + dblHi(double val) const + { + return fpToBits(val) >> 32; + } + + template + fpType + processNans(FPSCR &fpscr, bool &done, bool defaultNan, + fpType op1, fpType op2) const; + + template + fpType + binaryOp(FPSCR &fpscr, fpType op1, fpType op2, + fpType (*func)(fpType, fpType), + bool flush, bool defaultNan, uint32_t rMode) const; + + template + fpType + unaryOp(FPSCR &fpscr, fpType op1, + fpType (*func)(fpType), + bool flush, uint32_t rMode) const; + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } +}; + +class FpRegRegOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + + FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegImmOp : public FpOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + + FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm, + VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegRegImmOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + uint64_t imm; + + FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegRegRegOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + + FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegRegRegImmOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + uint64_t imm; + + FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, + IntRegIndex _op1, IntRegIndex _op2, + uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), imm(_imm) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} + +#endif //__ARCH_ARM_INSTS_VFP_HH__ diff --git a/simulators/gem5/src/arch/arm/interrupts.cc b/simulators/gem5/src/arch/arm/interrupts.cc new file mode 100644 index 00000000..c05ae984 --- /dev/null +++ b/simulators/gem5/src/arch/arm/interrupts.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "arch/arm/interrupts.hh" + +ArmISA::Interrupts * +ArmInterruptsParams::create() +{ + return new ArmISA::Interrupts(this); +} diff --git a/simulators/gem5/src/arch/arm/interrupts.hh b/simulators/gem5/src/arch/arm/interrupts.hh new file mode 100644 index 00000000..82c0bb71 --- /dev/null +++ b/simulators/gem5/src/arch/arm/interrupts.hh @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#ifndef __ARCH_ARM_INTERRUPT_HH__ +#define __ARCH_ARM_INTERRUPT_HH__ + +#include "arch/arm/faults.hh" +#include "arch/arm/isa_traits.hh" +#include "arch/arm/miscregs.hh" +#include "arch/arm/registers.hh" +#include "cpu/thread_context.hh" +#include "debug/Interrupt.hh" +#include "params/ArmInterrupts.hh" +#include "sim/sim_object.hh" + +namespace ArmISA +{ + +class Interrupts : public SimObject +{ + private: + BaseCPU * cpu; + + bool interrupts[NumInterruptTypes]; + uint64_t intStatus; + + public: + + void + setCPU(BaseCPU * _cpu) + { + cpu = _cpu; + } + + typedef ArmInterruptsParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + Interrupts(Params * p) : SimObject(p), cpu(NULL) + { + clearAll(); + } + + + void + post(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptTypes) + panic("int_num out of bounds\n"); + + if (index != 0) + panic("No support for other interrupt indexes\n"); + + interrupts[int_num] = true; + intStatus |= ULL(1) << int_num; + } + + void + clear(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptTypes) + panic("int_num out of bounds\n"); + + if (index != 0) + panic("No support for other interrupt indexes\n"); + + interrupts[int_num] = false; + intStatus &= ~(ULL(1) << int_num); + } + + void + clearAll() + { + DPRINTF(Interrupt, "Interrupts all cleared\n"); + intStatus = 0; + memset(interrupts, 0, sizeof(interrupts)); + } + + bool + checkInterrupts(ThreadContext *tc) const + { + if (!intStatus) + return false; + + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + + return ((interrupts[INT_IRQ] && !cpsr.i) || + (interrupts[INT_FIQ] && !cpsr.f) || + (interrupts[INT_ABT] && !cpsr.a) || + (interrupts[INT_RST]) || + (interrupts[INT_SEV])); + } + + /** + * Check the raw interrupt state. + * This function is used to check if a wfi operation should sleep. If there + * is an interrupt pending, even if it's masked, wfi doesn't sleep. + * @return any interrupts pending + */ + bool + checkRaw() const + { + return intStatus; + } + + + Fault + getInterrupt(ThreadContext *tc) + { + if (!intStatus) + return NoFault; + + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + + if (interrupts[INT_IRQ] && !cpsr.i) + return new Interrupt; + if (interrupts[INT_FIQ] && !cpsr.f) + return new FastInterrupt; + if (interrupts[INT_ABT] && !cpsr.a) + return new DataAbort(0, false, 0, + ArmFault::AsynchronousExternalAbort); + if (interrupts[INT_RST]) + return new Reset; + if (interrupts[INT_SEV]) + return new ArmSev; + + panic("intStatus and interrupts not in sync\n"); + } + + void + updateIntrInfo(ThreadContext *tc) + { + ; // nothing to do + } + + void + serialize(std::ostream &os) + { + SERIALIZE_ARRAY(interrupts, NumInterruptTypes); + SERIALIZE_SCALAR(intStatus); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(interrupts, NumInterruptTypes); + UNSERIALIZE_SCALAR(intStatus); + } +}; +} // namespace ARM_ISA + +#endif // __ARCH_ARM_INTERRUPT_HH__ diff --git a/simulators/gem5/src/arch/arm/intregs.hh b/simulators/gem5/src/arch/arm/intregs.hh new file mode 100644 index 00000000..3fe00b76 --- /dev/null +++ b/simulators/gem5/src/arch/arm/intregs.hh @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include + +#ifndef __ARCH_ARM_INTREGS_HH__ +#define __ARCH_ARM_INTREGS_HH__ + +#include "arch/arm/types.hh" + +namespace ArmISA +{ + +enum IntRegIndex +{ + /* All the unique register indices. */ + INTREG_R0, + INTREG_R1, + INTREG_R2, + INTREG_R3, + INTREG_R4, + INTREG_R5, + INTREG_R6, + INTREG_R7, + INTREG_R8, + INTREG_R9, + INTREG_R10, + INTREG_R11, + INTREG_R12, + INTREG_R13, + INTREG_SP = INTREG_R13, + INTREG_R14, + INTREG_LR = INTREG_R14, + INTREG_R15, + INTREG_PC = INTREG_R15, + + INTREG_R13_SVC, + INTREG_SP_SVC = INTREG_R13_SVC, + INTREG_R14_SVC, + INTREG_LR_SVC = INTREG_R14_SVC, + + INTREG_R13_MON, + INTREG_SP_MON = INTREG_R13_MON, + INTREG_R14_MON, + INTREG_LR_MON = INTREG_R14_MON, + + INTREG_R13_ABT, + INTREG_SP_ABT = INTREG_R13_ABT, + INTREG_R14_ABT, + INTREG_LR_ABT = INTREG_R14_ABT, + + INTREG_R13_UND, + INTREG_SP_UND = INTREG_R13_UND, + INTREG_R14_UND, + INTREG_LR_UND = INTREG_R14_UND, + + INTREG_R13_IRQ, + INTREG_SP_IRQ = INTREG_R13_IRQ, + INTREG_R14_IRQ, + INTREG_LR_IRQ = INTREG_R14_IRQ, + + INTREG_R8_FIQ, + INTREG_R9_FIQ, + INTREG_R10_FIQ, + INTREG_R11_FIQ, + INTREG_R12_FIQ, + INTREG_R13_FIQ, + INTREG_SP_FIQ = INTREG_R13_FIQ, + INTREG_R14_FIQ, + INTREG_LR_FIQ = INTREG_R14_FIQ, + + INTREG_ZERO, // Dummy zero reg since there has to be one. + INTREG_UREG0, + INTREG_UREG1, + INTREG_UREG2, + INTREG_CONDCODES_NZ, + INTREG_CONDCODES_C, + INTREG_CONDCODES_V, + INTREG_CONDCODES_GE, + INTREG_FPCONDCODES, + + NUM_INTREGS, + NUM_ARCH_INTREGS = INTREG_PC + 1, + + /* All the aliased indexes. */ + + /* USR mode */ + INTREG_R0_USR = INTREG_R0, + INTREG_R1_USR = INTREG_R1, + INTREG_R2_USR = INTREG_R2, + INTREG_R3_USR = INTREG_R3, + INTREG_R4_USR = INTREG_R4, + INTREG_R5_USR = INTREG_R5, + INTREG_R6_USR = INTREG_R6, + INTREG_R7_USR = INTREG_R7, + INTREG_R8_USR = INTREG_R8, + INTREG_R9_USR = INTREG_R9, + INTREG_R10_USR = INTREG_R10, + INTREG_R11_USR = INTREG_R11, + INTREG_R12_USR = INTREG_R12, + INTREG_R13_USR = INTREG_R13, + INTREG_SP_USR = INTREG_SP, + INTREG_R14_USR = INTREG_R14, + INTREG_LR_USR = INTREG_LR, + INTREG_R15_USR = INTREG_R15, + INTREG_PC_USR = INTREG_PC, + + /* SVC mode */ + INTREG_R0_SVC = INTREG_R0, + INTREG_R1_SVC = INTREG_R1, + INTREG_R2_SVC = INTREG_R2, + INTREG_R3_SVC = INTREG_R3, + INTREG_R4_SVC = INTREG_R4, + INTREG_R5_SVC = INTREG_R5, + INTREG_R6_SVC = INTREG_R6, + INTREG_R7_SVC = INTREG_R7, + INTREG_R8_SVC = INTREG_R8, + INTREG_R9_SVC = INTREG_R9, + INTREG_R10_SVC = INTREG_R10, + INTREG_R11_SVC = INTREG_R11, + INTREG_R12_SVC = INTREG_R12, + INTREG_PC_SVC = INTREG_PC, + INTREG_R15_SVC = INTREG_R15, + + /* MON mode */ + INTREG_R0_MON = INTREG_R0, + INTREG_R1_MON = INTREG_R1, + INTREG_R2_MON = INTREG_R2, + INTREG_R3_MON = INTREG_R3, + INTREG_R4_MON = INTREG_R4, + INTREG_R5_MON = INTREG_R5, + INTREG_R6_MON = INTREG_R6, + INTREG_R7_MON = INTREG_R7, + INTREG_R8_MON = INTREG_R8, + INTREG_R9_MON = INTREG_R9, + INTREG_R10_MON = INTREG_R10, + INTREG_R11_MON = INTREG_R11, + INTREG_R12_MON = INTREG_R12, + INTREG_PC_MON = INTREG_PC, + INTREG_R15_MON = INTREG_R15, + + /* ABT mode */ + INTREG_R0_ABT = INTREG_R0, + INTREG_R1_ABT = INTREG_R1, + INTREG_R2_ABT = INTREG_R2, + INTREG_R3_ABT = INTREG_R3, + INTREG_R4_ABT = INTREG_R4, + INTREG_R5_ABT = INTREG_R5, + INTREG_R6_ABT = INTREG_R6, + INTREG_R7_ABT = INTREG_R7, + INTREG_R8_ABT = INTREG_R8, + INTREG_R9_ABT = INTREG_R9, + INTREG_R10_ABT = INTREG_R10, + INTREG_R11_ABT = INTREG_R11, + INTREG_R12_ABT = INTREG_R12, + INTREG_PC_ABT = INTREG_PC, + INTREG_R15_ABT = INTREG_R15, + + /* UND mode */ + INTREG_R0_UND = INTREG_R0, + INTREG_R1_UND = INTREG_R1, + INTREG_R2_UND = INTREG_R2, + INTREG_R3_UND = INTREG_R3, + INTREG_R4_UND = INTREG_R4, + INTREG_R5_UND = INTREG_R5, + INTREG_R6_UND = INTREG_R6, + INTREG_R7_UND = INTREG_R7, + INTREG_R8_UND = INTREG_R8, + INTREG_R9_UND = INTREG_R9, + INTREG_R10_UND = INTREG_R10, + INTREG_R11_UND = INTREG_R11, + INTREG_R12_UND = INTREG_R12, + INTREG_PC_UND = INTREG_PC, + INTREG_R15_UND = INTREG_R15, + + /* IRQ mode */ + INTREG_R0_IRQ = INTREG_R0, + INTREG_R1_IRQ = INTREG_R1, + INTREG_R2_IRQ = INTREG_R2, + INTREG_R3_IRQ = INTREG_R3, + INTREG_R4_IRQ = INTREG_R4, + INTREG_R5_IRQ = INTREG_R5, + INTREG_R6_IRQ = INTREG_R6, + INTREG_R7_IRQ = INTREG_R7, + INTREG_R8_IRQ = INTREG_R8, + INTREG_R9_IRQ = INTREG_R9, + INTREG_R10_IRQ = INTREG_R10, + INTREG_R11_IRQ = INTREG_R11, + INTREG_R12_IRQ = INTREG_R12, + INTREG_PC_IRQ = INTREG_PC, + INTREG_R15_IRQ = INTREG_R15, + + /* FIQ mode */ + INTREG_R0_FIQ = INTREG_R0, + INTREG_R1_FIQ = INTREG_R1, + INTREG_R2_FIQ = INTREG_R2, + INTREG_R3_FIQ = INTREG_R3, + INTREG_R4_FIQ = INTREG_R4, + INTREG_R5_FIQ = INTREG_R5, + INTREG_R6_FIQ = INTREG_R6, + INTREG_R7_FIQ = INTREG_R7, + INTREG_PC_FIQ = INTREG_PC, + INTREG_R15_FIQ = INTREG_R15 +}; + +typedef IntRegIndex IntRegMap[NUM_ARCH_INTREGS]; + +const IntRegMap IntRegUsrMap = { + INTREG_R0_USR, INTREG_R1_USR, INTREG_R2_USR, INTREG_R3_USR, + INTREG_R4_USR, INTREG_R5_USR, INTREG_R6_USR, INTREG_R7_USR, + INTREG_R8_USR, INTREG_R9_USR, INTREG_R10_USR, INTREG_R11_USR, + INTREG_R12_USR, INTREG_R13_USR, INTREG_R14_USR, INTREG_R15_USR +}; + +static inline IntRegIndex +INTREG_USR(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegUsrMap[index]; +} + +const IntRegMap IntRegSvcMap = { + INTREG_R0_SVC, INTREG_R1_SVC, INTREG_R2_SVC, INTREG_R3_SVC, + INTREG_R4_SVC, INTREG_R5_SVC, INTREG_R6_SVC, INTREG_R7_SVC, + INTREG_R8_SVC, INTREG_R9_SVC, INTREG_R10_SVC, INTREG_R11_SVC, + INTREG_R12_SVC, INTREG_R13_SVC, INTREG_R14_SVC, INTREG_R15_SVC +}; + +static inline IntRegIndex +INTREG_SVC(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegSvcMap[index]; +} + +const IntRegMap IntRegMonMap = { + INTREG_R0_MON, INTREG_R1_MON, INTREG_R2_MON, INTREG_R3_MON, + INTREG_R4_MON, INTREG_R5_MON, INTREG_R6_MON, INTREG_R7_MON, + INTREG_R8_MON, INTREG_R9_MON, INTREG_R10_MON, INTREG_R11_MON, + INTREG_R12_MON, INTREG_R13_MON, INTREG_R14_MON, INTREG_R15_MON +}; + +static inline IntRegIndex +INTREG_MON(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegMonMap[index]; +} + +const IntRegMap IntRegAbtMap = { + INTREG_R0_ABT, INTREG_R1_ABT, INTREG_R2_ABT, INTREG_R3_ABT, + INTREG_R4_ABT, INTREG_R5_ABT, INTREG_R6_ABT, INTREG_R7_ABT, + INTREG_R8_ABT, INTREG_R9_ABT, INTREG_R10_ABT, INTREG_R11_ABT, + INTREG_R12_ABT, INTREG_R13_ABT, INTREG_R14_ABT, INTREG_R15_ABT +}; + +static inline IntRegIndex +INTREG_ABT(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegAbtMap[index]; +} + +const IntRegMap IntRegUndMap = { + INTREG_R0_UND, INTREG_R1_UND, INTREG_R2_UND, INTREG_R3_UND, + INTREG_R4_UND, INTREG_R5_UND, INTREG_R6_UND, INTREG_R7_UND, + INTREG_R8_UND, INTREG_R9_UND, INTREG_R10_UND, INTREG_R11_UND, + INTREG_R12_UND, INTREG_R13_UND, INTREG_R14_UND, INTREG_R15_UND +}; + +static inline IntRegIndex +INTREG_UND(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegUndMap[index]; +} + +const IntRegMap IntRegIrqMap = { + INTREG_R0_IRQ, INTREG_R1_IRQ, INTREG_R2_IRQ, INTREG_R3_IRQ, + INTREG_R4_IRQ, INTREG_R5_IRQ, INTREG_R6_IRQ, INTREG_R7_IRQ, + INTREG_R8_IRQ, INTREG_R9_IRQ, INTREG_R10_IRQ, INTREG_R11_IRQ, + INTREG_R12_IRQ, INTREG_R13_IRQ, INTREG_R14_IRQ, INTREG_R15_IRQ +}; + +static inline IntRegIndex +INTREG_IRQ(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegIrqMap[index]; +} + +const IntRegMap IntRegFiqMap = { + INTREG_R0_FIQ, INTREG_R1_FIQ, INTREG_R2_FIQ, INTREG_R3_FIQ, + INTREG_R4_FIQ, INTREG_R5_FIQ, INTREG_R6_FIQ, INTREG_R7_FIQ, + INTREG_R8_FIQ, INTREG_R9_FIQ, INTREG_R10_FIQ, INTREG_R11_FIQ, + INTREG_R12_FIQ, INTREG_R13_FIQ, INTREG_R14_FIQ, INTREG_R15_FIQ +}; + +static inline IntRegIndex +INTREG_FIQ(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegFiqMap[index]; +} + +static const unsigned intRegsPerMode = NUM_INTREGS; + +static inline int +intRegInMode(OperatingMode mode, int reg) +{ + assert(reg < NUM_ARCH_INTREGS); + return mode * intRegsPerMode + reg; +} + +} + +#endif diff --git a/simulators/gem5/src/arch/arm/isa.cc b/simulators/gem5/src/arch/arm/isa.cc new file mode 100644 index 00000000..2a5fbd2f --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa.cc @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2010-2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/arm/isa.hh" +#include "arch/arm/system.hh" +#include "cpu/checker/cpu.hh" +#include "debug/Arm.hh" +#include "debug/MiscRegs.hh" +#include "sim/faults.hh" +#include "sim/stat_control.hh" +#include "sim/system.hh" + +namespace ArmISA +{ + +void +ISA::clear() +{ + SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST]; + uint32_t midr = miscRegs[MISCREG_MIDR]; + memset(miscRegs, 0, sizeof(miscRegs)); + CPSR cpsr = 0; + cpsr.mode = MODE_USER; + miscRegs[MISCREG_CPSR] = cpsr; + updateRegMap(cpsr); + + SCTLR sctlr = 0; + sctlr.te = (bool)sctlr_rst.te; + sctlr.nmfi = (bool)sctlr_rst.nmfi; + sctlr.v = (bool)sctlr_rst.v; + sctlr.u = 1; + sctlr.xp = 1; + sctlr.rao2 = 1; + sctlr.rao3 = 1; + sctlr.rao4 = 1; + miscRegs[MISCREG_SCTLR] = sctlr; + miscRegs[MISCREG_SCTLR_RST] = sctlr_rst; + + // Preserve MIDR across reset + miscRegs[MISCREG_MIDR] = midr; + + /* Start with an event in the mailbox */ + miscRegs[MISCREG_SEV_MAILBOX] = 1; + + // Separate Instruction and Data TLBs. + miscRegs[MISCREG_TLBTR] = 1; + + MVFR0 mvfr0 = 0; + mvfr0.advSimdRegisters = 2; + mvfr0.singlePrecision = 2; + mvfr0.doublePrecision = 2; + mvfr0.vfpExceptionTrapping = 0; + mvfr0.divide = 1; + mvfr0.squareRoot = 1; + mvfr0.shortVectors = 1; + mvfr0.roundingModes = 1; + miscRegs[MISCREG_MVFR0] = mvfr0; + + MVFR1 mvfr1 = 0; + mvfr1.flushToZero = 1; + mvfr1.defaultNaN = 1; + mvfr1.advSimdLoadStore = 1; + mvfr1.advSimdInteger = 1; + mvfr1.advSimdSinglePrecision = 1; + mvfr1.advSimdHalfPrecision = 1; + mvfr1.vfpHalfPrecision = 1; + miscRegs[MISCREG_MVFR1] = mvfr1; + + // Reset values of PRRR and NMRR are implementation dependent + + miscRegs[MISCREG_PRRR] = + (1 << 19) | // 19 + (0 << 18) | // 18 + (0 << 17) | // 17 + (1 << 16) | // 16 + (2 << 14) | // 15:14 + (0 << 12) | // 13:12 + (2 << 10) | // 11:10 + (2 << 8) | // 9:8 + (2 << 6) | // 7:6 + (2 << 4) | // 5:4 + (1 << 2) | // 3:2 + 0; // 1:0 + miscRegs[MISCREG_NMRR] = + (1 << 30) | // 31:30 + (0 << 26) | // 27:26 + (0 << 24) | // 25:24 + (3 << 22) | // 23:22 + (2 << 20) | // 21:20 + (0 << 18) | // 19:18 + (0 << 16) | // 17:16 + (1 << 14) | // 15:14 + (0 << 12) | // 13:12 + (2 << 10) | // 11:10 + (0 << 8) | // 9:8 + (3 << 6) | // 7:6 + (2 << 4) | // 5:4 + (0 << 2) | // 3:2 + 0; // 1:0 + + miscRegs[MISCREG_CPACR] = 0; + miscRegs[MISCREG_FPSID] = 0x410430A0; + + // See section B4.1.84 of ARM ARM + // All values are latest for ARMv7-A profile + miscRegs[MISCREG_ID_ISAR0] = 0x02101111; + miscRegs[MISCREG_ID_ISAR1] = 0x02112111; + miscRegs[MISCREG_ID_ISAR2] = 0x21232141; + miscRegs[MISCREG_ID_ISAR3] = 0x01112131; + miscRegs[MISCREG_ID_ISAR4] = 0x10010142; + miscRegs[MISCREG_ID_ISAR5] = 0x00000000; + + //XXX We need to initialize the rest of the state. +} + +MiscReg +ISA::readMiscRegNoEffect(int misc_reg) +{ + assert(misc_reg < NumMiscRegs); + + int flat_idx; + if (misc_reg == MISCREG_SPSR) + flat_idx = flattenMiscIndex(misc_reg); + else + flat_idx = misc_reg; + MiscReg val = miscRegs[flat_idx]; + + DPRINTF(MiscRegs, "Reading From misc reg %d (%d) : %#x\n", + misc_reg, flat_idx, val); + return val; +} + + +MiscReg +ISA::readMiscReg(int misc_reg, ThreadContext *tc) +{ + ArmSystem *arm_sys; + + if (misc_reg == MISCREG_CPSR) { + CPSR cpsr = miscRegs[misc_reg]; + PCState pc = tc->pcState(); + cpsr.j = pc.jazelle() ? 1 : 0; + cpsr.t = pc.thumb() ? 1 : 0; + return cpsr; + } + if (misc_reg >= MISCREG_CP15_UNIMP_START) + panic("Unimplemented CP15 register %s read.\n", + miscRegName[misc_reg]); + + switch (misc_reg) { + case MISCREG_MPIDR: + arm_sys = dynamic_cast(tc->getSystemPtr()); + assert(arm_sys); + + if (arm_sys->multiProc) { + return 0x80000000 | // multiprocessor extensions available + tc->cpuId(); + } else { + return 0x80000000 | // multiprocessor extensions available + 0x40000000 | // in up system + tc->cpuId(); + } + break; + case MISCREG_ID_MMFR0: + return 0x03; // VMSAv7 support + case MISCREG_ID_MMFR2: + return 0x01230000; // no HW access | WFI stalling | ISB and DSB + // | all TLB maintenance | no Harvard + case MISCREG_ID_MMFR3: + return 0xF0102211; // SuperSec | Coherent TLB | Bcast Maint | + // BP Maint | Cache Maint Set/way | Cache Maint MVA + case MISCREG_CLIDR: + warn_once("The clidr register always reports 0 caches.\n"); + warn_once("clidr LoUIS field of 0b001 to match current " + "ARM implementations.\n"); + return 0x00200000; + case MISCREG_CCSIDR: + warn_once("The ccsidr register isn't implemented and " + "always reads as 0.\n"); + break; + case MISCREG_ID_PFR0: + warn("Returning thumbEE disabled for now since we don't support CP14" + "config registers and jumping to ThumbEE vectors\n"); + return 0x0031; // !ThumbEE | !Jazelle | Thumb | ARM + case MISCREG_ID_PFR1: + return 0x00001; // !Timer | !Virti | !M Profile | !TrustZone | ARMv4 + case MISCREG_CTR: + return 0x86468006; // V7, 64 byte cache line, load/exclusive is exact + case MISCREG_ACTLR: + warn("Not doing anything for miscreg ACTLR\n"); + break; + case MISCREG_PMCR: + case MISCREG_PMCCNTR: + case MISCREG_PMSELR: + warn("Not doing anything for read to miscreg %s\n", + miscRegName[misc_reg]); + break; + case MISCREG_CPSR_Q: + panic("shouldn't be reading this register seperately\n"); + case MISCREG_FPSCR_QC: + return readMiscRegNoEffect(MISCREG_FPSCR) & ~FpscrQcMask; + case MISCREG_FPSCR_EXC: + return readMiscRegNoEffect(MISCREG_FPSCR) & ~FpscrExcMask; + case MISCREG_L2CTLR: + { + // mostly unimplemented, just set NumCPUs field from sim and return + L2CTLR l2ctlr = 0; + // b00:1CPU to b11:4CPUs + l2ctlr.numCPUs = tc->getSystemPtr()->numContexts() - 1; + return l2ctlr; + } + case MISCREG_DBGDIDR: + /* For now just implement the version number. + * Return 0 as we don't support debug architecture yet. + */ + return 0; + case MISCREG_DBGDSCR_INT: + return 0; + } + return readMiscRegNoEffect(misc_reg); +} + +void +ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val) +{ + assert(misc_reg < NumMiscRegs); + + int flat_idx; + if (misc_reg == MISCREG_SPSR) + flat_idx = flattenMiscIndex(misc_reg); + else + flat_idx = misc_reg; + miscRegs[flat_idx] = val; + + DPRINTF(MiscRegs, "Writing to misc reg %d (%d) : %#x\n", misc_reg, + flat_idx, val); +} + +void +ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) +{ + + MiscReg newVal = val; + int x; + System *sys; + ThreadContext *oc; + + if (misc_reg == MISCREG_CPSR) { + updateRegMap(val); + + + CPSR old_cpsr = miscRegs[MISCREG_CPSR]; + int old_mode = old_cpsr.mode; + CPSR cpsr = val; + if (old_mode != cpsr.mode) { + tc->getITBPtr()->invalidateMiscReg(); + tc->getDTBPtr()->invalidateMiscReg(); + } + + DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n", + miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode); + PCState pc = tc->pcState(); + pc.nextThumb(cpsr.t); + pc.nextJazelle(cpsr.j); + + // Follow slightly different semantics if a CheckerCPU object + // is connected + CheckerCPU *checker = tc->getCheckerCpuPtr(); + if (checker) { + tc->pcStateNoRecord(pc); + } else { + tc->pcState(pc); + } + } else if (misc_reg >= MISCREG_CP15_UNIMP_START && + misc_reg < MISCREG_CP15_END) { + panic("Unimplemented CP15 register %s wrote with %#x.\n", + miscRegName[misc_reg], val); + } else { + switch (misc_reg) { + case MISCREG_CPACR: + { + + const uint32_t ones = (uint32_t)(-1); + CPACR cpacrMask = 0; + // Only cp10, cp11, and ase are implemented, nothing else should + // be writable + cpacrMask.cp10 = ones; + cpacrMask.cp11 = ones; + cpacrMask.asedis = ones; + newVal &= cpacrMask; + DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n", + miscRegName[misc_reg], newVal); + } + break; + case MISCREG_CSSELR: + warn_once("The csselr register isn't implemented.\n"); + return; + case MISCREG_FPSCR: + { + const uint32_t ones = (uint32_t)(-1); + FPSCR fpscrMask = 0; + fpscrMask.ioc = ones; + fpscrMask.dzc = ones; + fpscrMask.ofc = ones; + fpscrMask.ufc = ones; + fpscrMask.ixc = ones; + fpscrMask.idc = ones; + fpscrMask.len = ones; + fpscrMask.stride = ones; + fpscrMask.rMode = ones; + fpscrMask.fz = ones; + fpscrMask.dn = ones; + fpscrMask.ahp = ones; + fpscrMask.qc = ones; + fpscrMask.v = ones; + fpscrMask.c = ones; + fpscrMask.z = ones; + fpscrMask.n = ones; + newVal = (newVal & (uint32_t)fpscrMask) | + (miscRegs[MISCREG_FPSCR] & ~(uint32_t)fpscrMask); + } + break; + case MISCREG_CPSR_Q: + { + assert(!(newVal & ~CpsrMaskQ)); + newVal = miscRegs[MISCREG_CPSR] | newVal; + misc_reg = MISCREG_CPSR; + } + break; + case MISCREG_FPSCR_QC: + { + newVal = miscRegs[MISCREG_FPSCR] | (newVal & FpscrQcMask); + misc_reg = MISCREG_FPSCR; + } + break; + case MISCREG_FPSCR_EXC: + { + newVal = miscRegs[MISCREG_FPSCR] | (newVal & FpscrExcMask); + misc_reg = MISCREG_FPSCR; + } + break; + case MISCREG_FPEXC: + { + // vfpv3 architecture, section B.6.1 of DDI04068 + // bit 29 - valid only if fpexc[31] is 0 + const uint32_t fpexcMask = 0x60000000; + newVal = (newVal & fpexcMask) | + (miscRegs[MISCREG_FPEXC] & ~fpexcMask); + } + break; + case MISCREG_SCTLR: + { + DPRINTF(MiscRegs, "Writing SCTLR: %#x\n", newVal); + SCTLR sctlr = miscRegs[MISCREG_SCTLR]; + SCTLR new_sctlr = newVal; + new_sctlr.nmfi = (bool)sctlr.nmfi; + miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr; + tc->getITBPtr()->invalidateMiscReg(); + tc->getDTBPtr()->invalidateMiscReg(); + + // Check if all CPUs are booted with caches enabled + // so we can stop enforcing coherency of some kernel + // structures manually. + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + SCTLR other_sctlr = oc->readMiscRegNoEffect(MISCREG_SCTLR); + if (!other_sctlr.c && oc->status() != ThreadContext::Halted) + return; + } + + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + oc->getDTBPtr()->allCpusCaching(); + oc->getITBPtr()->allCpusCaching(); + + // If CheckerCPU is connected, need to notify it. + CheckerCPU *checker = oc->getCheckerCpuPtr(); + if (checker) { + checker->getDTBPtr()->allCpusCaching(); + checker->getITBPtr()->allCpusCaching(); + } + } + return; + } + case MISCREG_TLBTR: + case MISCREG_MVFR0: + case MISCREG_MVFR1: + case MISCREG_MPIDR: + case MISCREG_FPSID: + return; + case MISCREG_TLBIALLIS: + case MISCREG_TLBIALL: + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushAll(); + oc->getDTBPtr()->flushAll(); + + // If CheckerCPU is connected, need to notify it of a flush + CheckerCPU *checker = oc->getCheckerCpuPtr(); + if (checker) { + checker->getITBPtr()->flushAll(); + checker->getDTBPtr()->flushAll(); + } + } + return; + case MISCREG_ITLBIALL: + tc->getITBPtr()->flushAll(); + return; + case MISCREG_DTLBIALL: + tc->getDTBPtr()->flushAll(); + return; + case MISCREG_TLBIMVAIS: + case MISCREG_TLBIMVA: + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + oc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + + CheckerCPU *checker = oc->getCheckerCpuPtr(); + if (checker) { + checker->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + checker->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + } + } + return; + case MISCREG_TLBIASIDIS: + case MISCREG_TLBIASID: + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushAsid(bits(newVal, 7,0)); + oc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + CheckerCPU *checker = oc->getCheckerCpuPtr(); + if (checker) { + checker->getITBPtr()->flushAsid(bits(newVal, 7,0)); + checker->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + } + } + return; + case MISCREG_TLBIMVAAIS: + case MISCREG_TLBIMVAA: + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushMva(mbits(newVal, 31,12)); + oc->getDTBPtr()->flushMva(mbits(newVal, 31,12)); + + CheckerCPU *checker = oc->getCheckerCpuPtr(); + if (checker) { + checker->getITBPtr()->flushMva(mbits(newVal, 31,12)); + checker->getDTBPtr()->flushMva(mbits(newVal, 31,12)); + } + } + return; + case MISCREG_ITLBIMVA: + tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + return; + case MISCREG_DTLBIMVA: + tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + return; + case MISCREG_ITLBIASID: + tc->getITBPtr()->flushAsid(bits(newVal, 7,0)); + return; + case MISCREG_DTLBIASID: + tc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + return; + case MISCREG_ACTLR: + warn("Not doing anything for write of miscreg ACTLR\n"); + break; + case MISCREG_PMCR: + { + // Performance counters not implemented. Instead, interpret + // a reset command to this register to reset the simulator + // statistics. + // PMCR_E | PMCR_P | PMCR_C + const int ResetAndEnableCounters = 0x7; + if (newVal == ResetAndEnableCounters) { + inform("Resetting all simobject stats\n"); + Stats::schedStatEvent(false, true); + break; + } + } + case MISCREG_PMCCNTR: + case MISCREG_PMSELR: + warn("Not doing anything for write to miscreg %s\n", + miscRegName[misc_reg]); + break; + case MISCREG_V2PCWPR: + case MISCREG_V2PCWPW: + case MISCREG_V2PCWUR: + case MISCREG_V2PCWUW: + case MISCREG_V2POWPR: + case MISCREG_V2POWPW: + case MISCREG_V2POWUR: + case MISCREG_V2POWUW: + { + RequestPtr req = new Request; + unsigned flags; + BaseTLB::Mode mode; + Fault fault; + switch(misc_reg) { + case MISCREG_V2PCWPR: + flags = TLB::MustBeOne; + mode = BaseTLB::Read; + break; + case MISCREG_V2PCWPW: + flags = TLB::MustBeOne; + mode = BaseTLB::Write; + break; + case MISCREG_V2PCWUR: + flags = TLB::MustBeOne | TLB::UserMode; + mode = BaseTLB::Read; + break; + case MISCREG_V2PCWUW: + flags = TLB::MustBeOne | TLB::UserMode; + mode = BaseTLB::Write; + break; + default: + panic("Security Extensions not implemented!"); + } + warn("Translating via MISCREG in atomic mode! Fix Me!\n"); + req->setVirt(0, val, 1, flags, tc->pcState().pc(), + Request::funcMasterId); + fault = tc->getDTBPtr()->translateAtomic(req, tc, mode); + if (fault == NoFault) { + miscRegs[MISCREG_PAR] = + (req->getPaddr() & 0xfffff000) | + (tc->getDTBPtr()->getAttr() ); + DPRINTF(MiscRegs, + "MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n", + val, miscRegs[MISCREG_PAR]); + } + else { + // Set fault bit and FSR + FSR fsr = miscRegs[MISCREG_DFSR]; + miscRegs[MISCREG_PAR] = + (fsr.ext << 6) | + (fsr.fsHigh << 5) | + (fsr.fsLow << 1) | + 0x1; // F bit + } + return; + } + case MISCREG_CONTEXTIDR: + case MISCREG_PRRR: + case MISCREG_NMRR: + case MISCREG_DACR: + tc->getITBPtr()->invalidateMiscReg(); + tc->getDTBPtr()->invalidateMiscReg(); + break; + case MISCREG_CPSR_MODE: + // This miscreg is used by copy*Regs to set the CPSR mode + // without updating other CPSR variables. It's used to + // make sure the register map is in such a state that we can + // see all of the registers for the copy. + updateRegMap(val); + return; + case MISCREG_L2CTLR: + warn("miscreg L2CTLR (%s) written with %#x. ignored...\n", + miscRegName[misc_reg], uint32_t(val)); + } + } + setMiscRegNoEffect(misc_reg, newVal); +} + +} diff --git a/simulators/gem5/src/arch/arm/isa.hh b/simulators/gem5/src/arch/arm/isa.hh new file mode 100644 index 00000000..48840bf0 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa.hh @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ARM_ISA_HH__ +#define __ARCH_ARM_ISA_HH__ + +#include "arch/arm/registers.hh" +#include "arch/arm/tlb.hh" +#include "arch/arm/types.hh" +#include "debug/Checkpoint.hh" + +class ThreadContext; +class Checkpoint; +class EventManager; + +namespace ArmISA +{ + class ISA + { + protected: + MiscReg miscRegs[NumMiscRegs]; + const IntRegIndex *intRegMap; + + void + updateRegMap(CPSR cpsr) + { + switch (cpsr.mode) { + case MODE_USER: + case MODE_SYSTEM: + intRegMap = IntRegUsrMap; + break; + case MODE_FIQ: + intRegMap = IntRegFiqMap; + break; + case MODE_IRQ: + intRegMap = IntRegIrqMap; + break; + case MODE_SVC: + intRegMap = IntRegSvcMap; + break; + case MODE_MON: + intRegMap = IntRegMonMap; + break; + case MODE_ABORT: + intRegMap = IntRegAbtMap; + break; + case MODE_UNDEFINED: + intRegMap = IntRegUndMap; + break; + default: + panic("Unrecognized mode setting in CPSR.\n"); + } + } + + public: + void clear(); + + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg, ThreadContext *tc); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); + void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc); + + int + flattenIntIndex(int reg) + { + assert(reg >= 0); + if (reg < NUM_ARCH_INTREGS) { + return intRegMap[reg]; + } else if (reg < NUM_INTREGS) { + return reg; + } else { + int mode = reg / intRegsPerMode; + reg = reg % intRegsPerMode; + switch (mode) { + case MODE_USER: + case MODE_SYSTEM: + return INTREG_USR(reg); + case MODE_FIQ: + return INTREG_FIQ(reg); + case MODE_IRQ: + return INTREG_IRQ(reg); + case MODE_SVC: + return INTREG_SVC(reg); + case MODE_MON: + return INTREG_MON(reg); + case MODE_ABORT: + return INTREG_ABT(reg); + case MODE_UNDEFINED: + return INTREG_UND(reg); + default: + panic("Flattening into an unknown mode.\n"); + } + } + } + + int + flattenFloatIndex(int reg) + { + return reg; + } + + int + flattenMiscIndex(int reg) + { + if (reg == MISCREG_SPSR) { + int spsr_idx = NUM_MISCREGS; + CPSR cpsr = miscRegs[MISCREG_CPSR]; + switch (cpsr.mode) { + case MODE_USER: + warn("User mode does not have SPSR\n"); + spsr_idx = MISCREG_SPSR; + break; + case MODE_FIQ: + spsr_idx = MISCREG_SPSR_FIQ; + break; + case MODE_IRQ: + spsr_idx = MISCREG_SPSR_IRQ; + break; + case MODE_SVC: + spsr_idx = MISCREG_SPSR_SVC; + break; + case MODE_MON: + spsr_idx = MISCREG_SPSR_MON; + break; + case MODE_ABORT: + spsr_idx = MISCREG_SPSR_ABT; + break; + case MODE_UNDEFINED: + spsr_idx = MISCREG_SPSR_UND; + break; + default: + warn("Trying to access SPSR in an invalid mode: %d\n", + cpsr.mode); + spsr_idx = MISCREG_SPSR; + break; + } + return spsr_idx; + } + return reg; + } + + void serialize(EventManager *em, std::ostream &os) + { + DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n"); + SERIALIZE_ARRAY(miscRegs, NumMiscRegs); + } + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion) + { + DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n"); + UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs); + CPSR tmp_cpsr = miscRegs[MISCREG_CPSR]; + updateRegMap(tmp_cpsr); + } + + ISA() + { + SCTLR sctlr; + sctlr = 0; + miscRegs[MISCREG_SCTLR_RST] = sctlr; + + clear(); + } + }; +} + +#endif diff --git a/simulators/gem5/src/arch/arm/isa/bitfields.isa b/simulators/gem5/src/arch/arm/isa/bitfields.isa new file mode 100644 index 00000000..5a8b5db6 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/bitfields.isa @@ -0,0 +1,166 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Bitfield definitions. +// + +// Opcode fields +def bitfield ENCODING encoding; +def bitfield OPCODE opcode; +def bitfield MEDIA_OPCODE mediaOpcode; +def bitfield MEDIA_OPCODE2 mediaOpcode2; +def bitfield USEIMM useImm; +def bitfield OPCODE_24 opcode24; +def bitfield OPCODE_24_23 opcode24_23; +def bitfield OPCODE_23_20 opcode23_20; +def bitfield OPCODE_23_21 opcode23_21; +def bitfield OPCODE_22 opcode22; +def bitfield OPCODE_20 opcode20; +def bitfield OPCODE_19_16 opcode19_16; +def bitfield OPCODE_19 opcode19; +def bitfield OPCODE_18 opcode18; +def bitfield OPCODE_15_12 opcode15_12; +def bitfield OPCODE_15 opcode15; +def bitfield MISC_OPCODE miscOpcode; +def bitfield OPC2 opc2; +def bitfield OPCODE_7 opcode7; +def bitfield OPCODE_6 opcode6; +def bitfield OPCODE_4 opcode4; + +def bitfield IS_MISC isMisc; +def bitfield SEVEN_AND_FOUR sevenAndFour; + +def bitfield THUMB thumb; +def bitfield BIGTHUMB bigThumb; + +// Other +def bitfield COND_CODE condCode; +def bitfield S_FIELD sField; +def bitfield RN rn; +def bitfield RD rd; +def bitfield RT rt; +def bitfield SHIFT_SIZE shiftSize; +def bitfield SHIFT shift; +def bitfield RM rm; + +def bitfield RS rs; + +def bitfield PUSWL puswl; +def bitfield PREPOST puswl.prepost; +def bitfield UP puswl.up; +def bitfield PSRUSER puswl.psruser; +def bitfield WRITEBACK puswl.writeback; +def bitfield LOADOP puswl.loadOp; + +def bitfield PUBWL pubwl; + +def bitfield IMM imm; + +def bitfield IMMED_11_0 immed11_0; +def bitfield IMMED_7_0 immed7_0; + +def bitfield IMMED_HI_11_8 immedHi11_8; +def bitfield IMMED_LO_3_0 immedLo3_0; + +def bitfield IMMED_23_0 immed23_0; + +def bitfield CPNUM cpNum; +// Note that FP Regs are only 3 bits +def bitfield FN fn; +def bitfield FD fd; +def bitfield FPREGIMM fpRegImm; +// We can just use 3:0 for FM since the hard-wired FP regs are handled in +// float_regfile.hh +def bitfield FM fm; +def bitfield FPIMM fpImm; +def bitfield PUNWL punwl; + +// M5 instructions +def bitfield M5FUNC m5Func; + +// 16 bit thumb bitfields +def bitfield TOPCODE_15_13 topcode15_13; +def bitfield TOPCODE_13_11 topcode13_11; +def bitfield TOPCODE_12_11 topcode12_11; +def bitfield TOPCODE_12_10 topcode12_10; +def bitfield TOPCODE_11_9 topcode11_9; +def bitfield TOPCODE_11_8 topcode11_8; +def bitfield TOPCODE_10_9 topcode10_9; +def bitfield TOPCODE_10_8 topcode10_8; +def bitfield TOPCODE_9_6 topcode9_6; +def bitfield TOPCODE_7 topcode7; +def bitfield TOPCODE_7_6 topcode7_6; +def bitfield TOPCODE_7_5 topcode7_5; +def bitfield TOPCODE_7_4 topcode7_4; +def bitfield TOPCODE_3_0 topcode3_0; + +// 32 bit thumb bitfields +def bitfield HTOPCODE_12_11 htopcode12_11; +def bitfield HTOPCODE_10_9 htopcode10_9; +def bitfield HTOPCODE_9 htopcode9; +def bitfield HTOPCODE_9_8 htopcode9_8; +def bitfield HTOPCODE_9_5 htopcode9_5; +def bitfield HTOPCODE_9_4 htopcode9_4; +def bitfield HTOPCODE_8 htopcode8; +def bitfield HTOPCODE_8_7 htopcode8_7; +def bitfield HTOPCODE_8_6 htopcode8_6; +def bitfield HTOPCODE_8_5 htopcode8_5; +def bitfield HTOPCODE_7 htopcode7; +def bitfield HTOPCODE_7_5 htopcode7_5; +def bitfield HTOPCODE_6 htopcode6; +def bitfield HTOPCODE_6_5 htopcode6_5; +def bitfield HTOPCODE_5_4 htopcode5_4; +def bitfield HTOPCODE_4 htopcode4; + +def bitfield HTRN htrn; +def bitfield HTS hts; + +def bitfield LTOPCODE_15 ltopcode15; +def bitfield LTOPCODE_11_8 ltopcode11_8; +def bitfield LTOPCODE_7_6 ltopcode7_6; +def bitfield LTOPCODE_7_4 ltopcode7_4; +def bitfield LTOPCODE_4 ltopcode4; + +def bitfield LTRD ltrd; +def bitfield LTCOPROC ltcoproc; diff --git a/simulators/gem5/src/arch/arm/isa/copyright.txt b/simulators/gem5/src/arch/arm/isa/copyright.txt new file mode 100644 index 00000000..c9719739 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/copyright.txt @@ -0,0 +1,40 @@ +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007, 2008 +// The Florida State University +// All Rights Reserved +// +// This code is part of the M5 simulator. +// +// Permission is granted to use, copy, create derivative works and +// redistribute this software and such derivative works for any +// purpose, so long as the copyright notice above, this grant of +// permission, and the disclaimer below appear in all copies made; and +// so long as the name of The Florida State University is not used in +// any advertising or publicity pertaining to the use or distribution +// of this software without specific, written prior authorization. +// +// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE +// FLORIDA STATE UNIVERSITY AS TO ITS FITNESS FOR ANY PURPOSE, AND +// WITHOUT WARRANTY BY THE FLORIDA STATE UNIVERSITY OF ANY KIND, EITHER +// EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE. THE REGENTS OF THE FLORIDA STATE UNIVERSITY SHALL NOT BE +// LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, +// INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM +// ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN +// IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGES. +// +// Authors: Stephen R. Hines - modified for use in ARM version + diff --git a/simulators/gem5/src/arch/arm/isa/decoder/arm.isa b/simulators/gem5/src/arch/arm/isa/decoder/arm.isa new file mode 100644 index 00000000..4bd9d5cf --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/decoder/arm.isa @@ -0,0 +1,128 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010-2012 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// The actual ARM ISA decoder +// -------------------------- +// The following instructions are specified in the ARM ISA +// Specification. Decoding closely follows the style specified +// in the ARM ISA specification document starting with Table B.1 or 3-1 +// +// + +decode COND_CODE { +0xF: ArmUnconditional::armUnconditional(); +default: decode ENCODING { +format DataOp { + 0x0: decode SEVEN_AND_FOUR { + 1: decode MISC_OPCODE { + 0x9: decode PREPOST { + 0: ArmMultAndMultAcc::armMultAndMultAcc(); + 1: ArmSyncMem::armSyncMem(); + } + 0xb, 0xd, 0xf: AddrMode3::addrMode3(); + } + 0: decode IS_MISC { + 0: ArmDataProcReg::armDataProcReg(); + 1: decode OPCODE_7 { + 0x0: decode MISC_OPCODE { + 0x0: ArmMsrMrs::armMsrMrs(); + // bxj unimplemented, treated as bx + 0x1,0x2: ArmBxClz::armBxClz(); + 0x3: decode OPCODE { + 0x9: ArmBlxReg::armBlxReg(); + } + 0x5: ArmSatAddSub::armSatAddSub(); + 0x7: Breakpoint::bkpt(); + } + 0x1: ArmHalfWordMultAndMultAcc::armHalfWordMultAndMultAcc(); + } + } + } + 0x1: decode IS_MISC { + 0: ArmDataProcImm::armDataProcImm(); + 1: ArmMisc::armMisc(); + } + 0x2: AddrMode2::addrMode2(True); + 0x3: decode OPCODE_4 { + 0: AddrMode2::addrMode2(False); + 1: decode OPCODE_24_23 { + 0x0: ArmParallelAddSubtract::armParallelAddSubtract(); + 0x1: ArmPackUnpackSatReverse::armPackUnpackSatReverse(); + 0x2: ArmSignedMultiplies::armSignedMultiplies(); + 0x3: decode MEDIA_OPCODE { + 0x1F: decode OPC2 { + default: ArmMiscMedia::armMiscMedia(); + } + default: ArmMiscMedia::armMiscMedia(); + } + } + } + 0x4: ArmMacroMem::armMacroMem(); + 0x5: decode OPCODE_24 { + 0: ArmBBlxImm::armBBlxImm(); + 1: ArmBlBlxImm::armBlBlxImm(); + } + 0x6: decode CPNUM { + 0xa, 0xb: ExtensionRegLoadStore::extensionRegLoadStore(); + } + 0x7: decode OPCODE_24 { + 0: decode OPCODE_4 { + 0: decode CPNUM { + 0xa, 0xb: VfpData::vfpData(); + } // CPNUM + 1: decode CPNUM { // 27-24=1110,4 ==1 + 0x1: M5ops::m5ops(); + 0xa, 0xb: ShortFpTransfer::shortFpTransfer(); + 0xe: McrMrc14::mcrMrc14(); + 0xf: McrMrc15::mcrMrc15(); + } // CPNUM (OP4 == 1) + } //OPCODE_4 + + 1: Svc::svc(); + } // OPCODE_24 + +} +} +} + diff --git a/simulators/gem5/src/arch/arm/isa/decoder/decoder.isa b/simulators/gem5/src/arch/arm/isa/decoder/decoder.isa new file mode 100644 index 00000000..cf7d1787 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/decoder/decoder.isa @@ -0,0 +1,48 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2009 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +decode THUMB default Unknown::unknown() { +0: +##include "arm.isa" +1: +##include "thumb.isa" +} diff --git a/simulators/gem5/src/arch/arm/isa/decoder/thumb.isa b/simulators/gem5/src/arch/arm/isa/decoder/thumb.isa new file mode 100644 index 00000000..f54cc728 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/decoder/thumb.isa @@ -0,0 +1,171 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010-2012 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2009 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +decode BIGTHUMB { + // 16 bit thumb instructions. + 0: decode TOPCODE_15_13 { + 0x0, 0x1: Thumb16ShiftAddSubMoveCmp::thumb16ShiftAddMoveCmp(); + 0x2: decode TOPCODE_12_10 { + 0x0: Thumb16DataProcessing::thumb16DataProcessing(); + 0x1: Thumb16SpecDataAndBx::thumb16SpecDataAndBx(); + 0x2, 0x3: Thumb16MemLit::thumb16MemLit(); + default: Thumb16MemReg::thumb16MemReg(); + } + 0x3, 0x4: Thumb16MemImm::thumb16MemImm(); + 0x5: decode TOPCODE_12_11 { + 0x0: Thumb16Adr::thumb16Adr(); + 0x1: Thumb16AddSp::thumb16AddSp(); //sp, immediate + 0x2, 0x3: Thumb16Misc::thumb16Misc(); + } + 0x6: decode TOPCODE_12_11 { + 0x0, 0x1: Thumb16MacroMem::thumb16MacroMem(); + 0x2, 0x3: Thumb16CondBranchAndSvc::thumb16CondBranchAndSvc(); + } + 0x7: decode TOPCODE_12_11 { + 0x0: Thumb16UncondBranch::thumb16UncondBranch(); + } + } + + // 32 bit thumb instructions. + 1: decode HTOPCODE_12_11 { + 0x1: decode HTOPCODE_10_9 { + 0x0: decode HTOPCODE_6 { + 0x0: decode HTOPCODE_8_7 { + 0x0, 0x3: Thumb32SrsRfe::thumb32SrsRfe(); + // This uses the same encoding as regular ARM. + default: ArmMacroMem::armMacroMem(); + } + 0x1: Thumb32LdrStrDExTbh::thumb32LdrStrDExTbh(); + } + 0x1: Thumb32DataProcShiftReg::thumb32DataProcShiftReg(); + default: decode HTOPCODE_9_8 { + 0x2: decode LTOPCODE_4 { + 0x0: decode LTCOPROC { + 0xa, 0xb: VfpData::vfpData(); + default: WarnUnimpl::cdp(); // cdp2 + } + 0x1: decode LTCOPROC { + 0x1: M5ops::m5ops(); + 0xa, 0xb: ShortFpTransfer::shortFpTransfer(); + 0xe: McrMrc14::mcrMrc14(); + 0xf: McrMrc15::mcrMrc15(); + } + } + 0x3: ThumbNeonData::ThumbNeonData(); + default: decode LTCOPROC { + 0xa, 0xb: ExtensionRegLoadStore::extensionRegLoadStre(); + 0xf: decode HTOPCODE_9_4 { + 0x00: Unknown::undefined(); + 0x04: WarnUnimpl::mcrr(); // mcrr2 + 0x05: WarnUnimpl::mrrc(); // mrrc2 + 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, + 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e: + WarnUnimpl::stc(); // stc2 + 0x03, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, + 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f: + decode HTRN { + 0xf: WarnUnimpl::ldc(); // ldc2 (literal) + default: WarnUnimpl::ldc(); // ldc2 (immediate) + } + } + } + } + } + 0x2: decode LTOPCODE_15 { + 0x0: decode HTOPCODE_9 { + 0x0: Thumb32DataProcModImm::thumb32DataProcModImm(); + 0x1: Thumb32DataProcPlainBin::thumb32DataProcPlainBin(); + } + 0x1: Thumb32BranchesAndMiscCtrl::thumb32BranchesAndMiscCtrl(); + } + 0x3: decode HTOPCODE_10_9 { + 0x0: decode HTOPCODE_4 { + 0x0: decode HTOPCODE_8 { + 0x0: Thumb32StoreSingle::thumb32StoreSingle(); + 0x1: ThumbNeonMem::thumbNeonMem(); + } + 0x1: decode HTOPCODE_6_5 { + 0x0: LoadByteMemoryHints::loadByteMemoryHints(); + 0x1: LoadHalfwordMemoryHints::loadHalfwordMemoryHints(); + 0x2: Thumb32LoadWord::thumb32LoadWord(); + } + } + 0x1: decode HTOPCODE_8_7 { + 0x2: Thumb32MulMulAccAndAbsDiff::thumb32MulMulAccAndAbsDiff(); + 0x3: Thumb32LongMulMulAccAndDiv::thumb32LongMulMulAccAndDiv(); + default: Thumb32DataProcReg::thumb32DataProcReg(); + } + default: decode HTOPCODE_9_8 { + 0x2: decode LTOPCODE_4 { + 0x0: decode LTCOPROC { + 0xa, 0xb: VfpData::vfpData(); + default: WarnUnimpl::cdp(); // cdp2 + } + 0x1: decode LTCOPROC { + 0x1: M5ops::m5ops(); + 0xa, 0xb: ShortFpTransfer::shortFpTransfer(); + 0xe: McrMrc14::mcrMrc14(); + 0xf: McrMrc15::mcrMrc15(); + } + } + 0x3: ThumbNeonData::thumbNeonData(); + default: decode LTCOPROC { + 0xa, 0xb: ExtensionRegLoadStore::extensionRegLoadStre(); + 0xf: decode HTOPCODE_9_4 { + 0x00: Unknown::undefined(); + 0x04: WarnUnimpl::mcrr(); // mcrr2 + 0x05: WarnUnimpl::mrrc(); // mrrc2 + 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, + 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e: + WarnUnimpl::stc(); // stc2 + 0x03, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, + 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f: + decode HTRN { + 0xf: WarnUnimpl::ldc(); // ldc2 (literal) + default: WarnUnimpl::ldc(); // ldc2 (immediate) + } + } + } + } + } + } +} diff --git a/simulators/gem5/src/arch/arm/isa/formats/basic.isa b/simulators/gem5/src/arch/arm/isa/formats/basic.isa new file mode 100644 index 00000000..43ee3768 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/formats/basic.isa @@ -0,0 +1,38 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +// The most basic instruction format... +def format BasicOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'ArmStaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/simulators/gem5/src/arch/arm/isa/formats/branch.isa b/simulators/gem5/src/arch/arm/isa/formats/branch.isa new file mode 100644 index 00000000..f1b17ec9 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/formats/branch.isa @@ -0,0 +1,282 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Control transfer instructions +// + +def format ArmBBlxImm() {{ + decode_block = ''' + if (machInst.condCode == 0xF) { + int32_t imm = (sext<26>(bits(machInst, 23, 0) << 2)) | + (bits(machInst, 24) << 1); + return new BlxImm(machInst, imm, COND_UC); + } else { + return new B(machInst, sext<26>(bits(machInst, 23, 0) << 2), + (ConditionCode)(uint32_t)machInst.condCode); + } + ''' +}}; + +def format ArmBlBlxImm() {{ + decode_block = ''' + if (machInst.condCode == 0xF) { + int32_t imm = (sext<26>(bits(machInst, 23, 0) << 2)) | + (bits(machInst, 24) << 1); + return new BlxImm(machInst, imm, COND_UC); + } else { + return new Bl(machInst, sext<26>(bits(machInst, 23, 0) << 2), + (ConditionCode)(uint32_t)machInst.condCode); + } + ''' +}}; + +def format ArmBxClz() {{ + decode_block = ''' + { + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (OPCODE == 0x9) { + return new BxReg(machInst, rm, + (ConditionCode)(uint32_t)machInst.condCode); + } else if (OPCODE == 0xb) { + return new Clz(machInst, rd, rm); + } else { + return new Unknown(machInst); + } + } + ''' +}}; + +def format ArmBlxReg() {{ + decode_block = ''' + return new BlxReg(machInst, (IntRegIndex)(uint32_t)bits(machInst, 3, 0), + (ConditionCode)(uint32_t)machInst.condCode); + ''' +}}; + +def format Thumb16CondBranchAndSvc() {{ + decode_block = ''' + if (bits(machInst, 11, 9) != 0x7) { + return new B(machInst, sext<9>(bits(machInst, 7, 0) << 1), + (ConditionCode)(uint32_t)bits(machInst, 11, 8)); + } else if (bits(machInst, 8)) { + return new Svc(machInst); + } else { + // This space will not be allocated in the future. + return new Unknown(machInst); + } + ''' +}}; + +def format Thumb16UncondBranch() {{ + decode_block = ''' + return new B(machInst, sext<12>(bits(machInst, 10, 0) << 1), COND_UC); + ''' +}}; + +def format Thumb32BranchesAndMiscCtrl() {{ + decode_block = ''' + { + const uint32_t op = bits(machInst, 26, 20); + const uint32_t op1 = bits(machInst, 14, 12); + switch (op1 & 0x5) { + case 0x0: + if (op == 127) { + if (op1 & 0x2) { + // Permanently undefined. + return new Unknown(machInst); + } else { + return new WarnUnimplemented("smc", machInst); + } + } else if ((op & 0x38) != 0x38) { + const uint32_t s = bits(machInst, 26); + const uint32_t j1 = bits(machInst, 13); + const uint32_t j2 = bits(machInst, 11); + const uint32_t imm6 = bits(machInst, 21, 16); + const uint32_t imm11 = bits(machInst, 10, 0); + const int32_t imm = sext<21>((s << 20) | + (j2 << 19) | (j1 << 18) | + (imm6 << 12) | (imm11 << 1)); + return new B(machInst, imm, + (ConditionCode)(uint32_t)bits(machInst, 25, 22)); + } else { + switch (op) { + case 0x38: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint8_t byteMask = bits(machInst, 11, 8); + return new MsrCpsrReg(machInst, rn, byteMask); + } + case 0x39: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint8_t byteMask = bits(machInst, 11, 8); + return new MsrSpsrReg(machInst, rn, byteMask); + } + case 0x3a: + { + const uint32_t op1 = bits(machInst, 10, 8); + const uint32_t op2 = bits(machInst, 7, 0); + if (op1 != 0) { + const bool enable = bits(machInst, 10, 9) == 0x2; + const uint32_t mods = bits(machInst, 8, 0) | + ((enable ? 1 : 0) << 9); + return new Cps(machInst, mods); + } else if ((op2 & 0xf0) == 0xf0) { + return new Dbg(machInst); + } else { + switch (op2) { + case 0x0: + return new NopInst(machInst); + case 0x1: + return new YieldInst(machInst); + case 0x2: + return new WfeInst(machInst); + case 0x3: + return new WfiInst(machInst); + case 0x4: + return new SevInst(machInst); + default: + break; + } + } + break; + } + case 0x3b: + { + const uint32_t op = bits(machInst, 7, 4); + switch (op) { + case 0x0: + return new Leavex(machInst); + case 0x1: + return new Enterx(machInst); + case 0x2: + return new Clrex(machInst); + case 0x4: + return new Dsb(machInst); + case 0x5: + return new Dmb(machInst); + case 0x6: + return new Isb(machInst); + default: + break; + } + break; + } + case 0x3c: + { + // On systems that don't support bxj, bxj == bx + return new BxReg(machInst, + (IntRegIndex)(uint32_t)bits(machInst, 19, 16), + COND_UC); + } + case 0x3d: + { + const uint32_t imm32 = bits(machInst, 7, 0); + return new SubsImmPclr(machInst, INTREG_PC, INTREG_LR, + imm32, false); + } + case 0x3e: + { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + return new MrsCpsr(machInst, rd); + } + case 0x3f: + { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + return new MrsSpsr(machInst, rd); + } + } + break; + } + case 0x1: + { + const uint32_t s = bits(machInst, 26); + const uint32_t i1 = !(bits(machInst, 13) ^ s); + const uint32_t i2 = !(bits(machInst, 11) ^ s); + const uint32_t imm10 = bits(machInst, 25, 16); + const uint32_t imm11 = bits(machInst, 10, 0); + const int32_t imm = sext<25>((s << 24) | + (i1 << 23) | (i2 << 22) | + (imm10 << 12) | (imm11 << 1)); + return new B(machInst, imm, COND_UC); + } + case 0x4: + { + if (bits(machInst, 0) == 1) { + return new Unknown(machInst); + } + const uint32_t s = bits(machInst, 26); + const uint32_t i1 = !(bits(machInst, 13) ^ s); + const uint32_t i2 = !(bits(machInst, 11) ^ s); + const uint32_t imm10h = bits(machInst, 25, 16); + const uint32_t imm10l = bits(machInst, 10, 1); + const int32_t imm = sext<25>((s << 24) | + (i1 << 23) | (i2 << 22) | + (imm10h << 12) | (imm10l << 2)); + return new BlxImm(machInst, imm, COND_UC); + } + case 0x5: + { + const uint32_t s = bits(machInst, 26); + const uint32_t i1 = !(bits(machInst, 13) ^ s); + const uint32_t i2 = !(bits(machInst, 11) ^ s); + const uint32_t imm10 = bits(machInst, 25, 16); + const uint32_t imm11 = bits(machInst, 10, 0); + const int32_t imm = sext<25>((s << 24) | + (i1 << 23) | (i2 << 22) | + (imm10 << 12) | (imm11 << 1)); + return new Bl(machInst, imm, COND_UC); + } + default: + break; + } + return new Unknown(machInst); + } + ''' +}}; diff --git a/simulators/gem5/src/arch/arm/isa/formats/breakpoint.isa b/simulators/gem5/src/arch/arm/isa/formats/breakpoint.isa new file mode 100644 index 00000000..1825d087 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/formats/breakpoint.isa @@ -0,0 +1,93 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Breakpoint instructions +// + +output header {{ + /** + * Static instruction class for Breakpoint (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Breakpoint : public ArmStaticInst + { + public: + /// Constructor + Breakpoint(ExtMachInst _machInst) + : ArmStaticInst("Breakpoint", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + Breakpoint::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x)", "Breakpoint", machInst); + } +}}; + +output exec {{ + Fault + Breakpoint::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return new PrefetchAbort(xc->pcState().pc(), ArmFault::DebugEvent); + } +}}; + +def format Breakpoint() {{ + decode_block = 'return new Breakpoint(machInst);\n' +}}; + diff --git a/simulators/gem5/src/arch/arm/isa/formats/data.isa b/simulators/gem5/src/arch/arm/isa/formats/data.isa new file mode 100644 index 00000000..3ee178f0 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/formats/data.isa @@ -0,0 +1,1534 @@ +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +def format ArmMiscMedia() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 7, 5); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (op1 == 0 && op2 == 0) { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + if (ra == 0xf) { + return new Usad8(machInst, rd, rn, rm); + } else { + return new Usada8(machInst, rd, rn, rm, ra); + } + } else if (bits(op2, 1, 0) == 0x2) { + const uint32_t lsb = bits(machInst, 11, 7); + const uint32_t msb = lsb + bits(machInst, 20, 16); + if (bits(op1, 2, 1) == 0x3) { + return new Ubfx(machInst, ra, rn, lsb, msb); + } else if (bits(op1, 2, 1) == 0x1) { + return new Sbfx(machInst, ra, rn, lsb, msb); + } + } else if (bits(op2, 1, 0) == 0x0 && bits(op1, 2, 1) == 0x2) { + const uint32_t lsb = bits(machInst, 11, 7); + const uint32_t msb = bits(machInst, 20, 16); + if (rn == 0xf) { + return new Bfc(machInst, ra, ra, lsb, msb); + } else { + return new Bfi(machInst, ra, rn, lsb, msb); + } + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmDataProcReg() {{ + pclr = ''' + return new %(className)ssRegPclr(machInst, %(dest)s, + %(op1)s, rm, imm5, + type); + ''' + instDecode = ''' + case %(opcode)#x: + if (immShift) { + if (setCc) { + if (%(dest)s == INTREG_PC) { + %(pclr)s + } else { + return new %(className)sRegCc(machInst, %(dest)s, + %(op1)s, rm, imm5, type); + } + } else { + return new %(className)sReg(machInst, %(dest)s, %(op1)s, + rm, imm5, type); + } + } else { + if (setCc) { + return new %(className)sRegRegCc(machInst, %(dest)s, + %(op1)s, rm, rs, type); + } else { + return new %(className)sRegReg(machInst, %(dest)s, + %(op1)s, rm, rs, type); + } + } + break; + ''' + + def instCode(opcode, mnem, useDest = True, useOp1 = True): + global pclr + if useDest: + dest = "rd" + else: + dest = "INTREG_ZERO" + if useOp1: + op1 = "rn" + else: + op1 = "INTREG_ZERO" + global instDecode, pclrCode + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": dest, + "op1": op1 } + if useDest: + substDict["pclr"] = pclr % substDict + else: + substDict["pclr"] = "" + return instDecode % substDict + + decode_block = ''' + { + const bool immShift = (bits(machInst, 4) == 0); + const bool setCc = (bits(machInst, 20) == 1); + const uint32_t imm5 = bits(machInst, 11, 7); + const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5); + const IntRegIndex rd = (IntRegIndex)(uint32_t)RD; + const IntRegIndex rn = (IntRegIndex)(uint32_t)RN; + const IntRegIndex rm = (IntRegIndex)(uint32_t)RM; + const IntRegIndex rs = (IntRegIndex)(uint32_t)RS; + switch (OPCODE) { + ''' + decode_block += instCode(0x0, "and") + decode_block += instCode(0x1, "eor") + decode_block += instCode(0x2, "sub") + decode_block += instCode(0x3, "rsb") + decode_block += instCode(0x4, "add") + decode_block += instCode(0x5, "adc") + decode_block += instCode(0x6, "sbc") + decode_block += instCode(0x7, "rsc") + decode_block += instCode(0x8, "tst", useDest = False) + decode_block += instCode(0x9, "teq", useDest = False) + decode_block += instCode(0xa, "cmp", useDest = False) + decode_block += instCode(0xb, "cmn", useDest = False) + decode_block += instCode(0xc, "orr") + decode_block += instCode(0xd, "mov", useOp1 = False) + decode_block += instCode(0xe, "bic") + decode_block += instCode(0xf, "mvn", useOp1 = False) + decode_block += ''' + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format ArmPackUnpackSatReverse() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t a = bits(machInst, 19, 16); + const uint32_t op2 = bits(machInst, 7, 5); + if (bits(op2, 0) == 0) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t satImm = bits(machInst, 20, 16); + const uint32_t imm = bits(machInst, 11, 7); + const ArmShiftType type = + (ArmShiftType)(uint32_t)bits(machInst, 6, 5); + if (op1 == 0) { + if (type) { + return new PkhtbReg(machInst, rd, (IntRegIndex)a, + rn, imm, type); + } else { + return new PkhbtReg(machInst, rd, (IntRegIndex)a, + rn, imm, type); + } + } else if (bits(op1, 2, 1) == 1) { + return new Ssat(machInst, rd, satImm + 1, rn, imm, type); + } else if (bits(op1, 2, 1) == 3) { + return new Usat(machInst, rd, satImm, rn, imm, type); + } + return new Unknown(machInst); + } + switch (op1) { + case 0x0: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (op2 == 0x3) { + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Sxtb16(machInst, rd, rotation, rm); + } else { + return new Sxtab16(machInst, rd, rn, rm, rotation); + } + } else if (op2 == 0x5) { + return new Sel(machInst, rd, rn, rm); + } + } + break; + case 0x2: + if (op2 == 0x1) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t satImm = bits(machInst, 20, 16); + return new Ssat16(machInst, rd, satImm + 1, rn); + } else if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Sxtb(machInst, rd, rotation, rm); + } else { + return new Sxtab(machInst, rd, rn, rm, rotation); + } + } + break; + case 0x3: + if (op2 == 0x1) { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + return new Rev(machInst, rd, rm); + } else if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Sxth(machInst, rd, rotation, rm); + } else { + return new Sxtah(machInst, rd, rn, rm, rotation); + } + } else if (op2 == 0x5) { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + return new Rev16(machInst, rd, rm); + } + break; + case 0x4: + if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Uxtb16(machInst, rd, rotation, rm); + } else { + return new Uxtab16(machInst, rd, rn, rm, rotation); + } + } + break; + case 0x6: + if (op2 == 0x1) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t satImm = bits(machInst, 20, 16); + return new Usat16(machInst, rd, satImm, rn); + } else if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Uxtb(machInst, rd, rotation, rm); + } else { + return new Uxtab(machInst, rd, rn, rm, rotation); + } + } + break; + case 0x7: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (op2 == 0x1) { + return new Rbit(machInst, rd, rm); + } else if (op2 == 0x3) { + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Uxth(machInst, rd, rotation, rm); + } else { + return new Uxtah(machInst, rd, rn, rm, rotation); + } + } else if (op2 == 0x5) { + return new Revsh(machInst, rd, rm); + } + } + break; + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmParallelAddSubtract() {{ + decode_block=''' + { + const uint32_t op1 = bits(machInst, 21, 20); + const uint32_t op2 = bits(machInst, 7, 5); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (bits(machInst, 22) == 0) { + switch (op1) { + case 0x1: + switch (op2) { + case 0x0: + return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new SasxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op2) { + case 0x0: + return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new QasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new QsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x3: + switch (op2) { + case 0x0: + return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new ShasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new ShsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } else { + switch (op1) { + case 0x1: + switch (op2) { + case 0x0: + return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new UasxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op2) { + case 0x0: + return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new UqasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UqsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x3: + switch (op2) { + case 0x0: + return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new UhasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UhsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmDataProcImm() {{ + pclr = ''' + return new %(className)ssImmPclr(machInst, %(dest)s, + %(op1)s, imm, false); + ''' + adr = ''' + return new AdrImm(machInst, %(dest)s, %(add)s, + imm, false); + ''' + instDecode = ''' + case %(opcode)#x: + if (setCc) { + if (%(pclrInst)s && %(dest)s == INTREG_PC) { + %(pclr)s + } else { + return new %(className)sImmCc(machInst, %(dest)s, %(op1)s, + imm, rotC); + } + } else { + if (%(adrInst)s && %(op1)s == INTREG_PC) { + %(adr)s + } else { + return new %(className)sImm(machInst, %(dest)s, %(op1)s, + imm, rotC); + } + } + break; + ''' + + def instCode(opcode, mnem, useDest = True, useOp1 = True): + global instDecode, pclr, adr + if useDest: + dest = "rd" + else: + dest = "INTREG_ZERO" + if useOp1: + op1 = "rn" + else: + op1 = "INTREG_ZERO" + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": dest, + "op1": op1, + "adr": "", + "adrInst": "false" } + if useDest: + substDict["pclrInst"] = "true" + substDict["pclr"] = pclr % substDict + else: + substDict["pclrInst"] = "false" + substDict["pclr"] = "" + return instDecode % substDict + + def adrCode(opcode, mnem, add="1"): + global instDecode, pclr, adr + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": "rd", + "op1": "rn", + "add": add, + "pclrInst": "true", + "adrInst": "true" } + substDict["pclr"] = pclr % substDict + substDict["adr"] = adr % substDict + return instDecode % substDict + + decode_block = ''' + { + const bool setCc = (bits(machInst, 20) == 1); + const uint32_t unrotated = bits(machInst, 7, 0); + const uint32_t rotation = (bits(machInst, 11, 8) << 1); + const bool rotC = (rotation != 0); + const uint32_t imm = rotate_imm(unrotated, rotation); + const IntRegIndex rd = (IntRegIndex)(uint32_t)RD; + const IntRegIndex rn = (IntRegIndex)(uint32_t)RN; + switch (OPCODE) { + ''' + decode_block += instCode(0x0, "and") + decode_block += instCode(0x1, "eor") + decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0") + decode_block += instCode(0x3, "rsb") + decode_block += adrCode(0x4, "add", add="(IntRegIndex)1") + decode_block += instCode(0x5, "adc") + decode_block += instCode(0x6, "sbc") + decode_block += instCode(0x7, "rsc") + decode_block += instCode(0x8, "tst", useDest = False) + decode_block += instCode(0x9, "teq", useDest = False) + decode_block += instCode(0xa, "cmp", useDest = False) + decode_block += instCode(0xb, "cmn", useDest = False) + decode_block += instCode(0xc, "orr") + decode_block += instCode(0xd, "mov", useOp1 = False) + decode_block += instCode(0xe, "bic") + decode_block += instCode(0xf, "mvn", useOp1 = False) + decode_block += ''' + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format ArmSatAddSub() {{ + decode_block = ''' + { + IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (OPCODE) { + case 0x8: + return new QaddRegCc(machInst, rd, rm, rn, 0, LSL); + case 0x9: + return new QsubRegCc(machInst, rd, rm, rn, 0, LSL); + case 0xa: + return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL); + case 0xb: + return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL); + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb32DataProcReg() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 23, 20); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint32_t op2 = bits(machInst, 7, 4); + if (bits(machInst, 15, 12) != 0xf) { + return new Unknown(machInst); + } + if (bits(op1, 3) != 1) { + if (op2 == 0) { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (bits(op1, 2, 0)) { + case 0x0: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, LSL); + case 0x1: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, LSL); + case 0x2: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, LSR); + case 0x3: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, LSR); + case 0x4: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, ASR); + case 0x5: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, ASR); + case 0x6: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, ROR); + case 0x7: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, ROR); + } + } else if (bits(op2, 3) == 0) { + return new Unknown(machInst); + } else { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 5, 4) << 3; + switch (bits(op1, 2, 0)) { + case 0x0: + if (rn == 0xf) { + return new Sxth(machInst, rd, rotation, rm); + } else { + return new Sxtah(machInst, rd, rn, rm, rotation); + } + case 0x1: + if (rn == 0xf) { + return new Uxth(machInst, rd, rotation, rm); + } else { + return new Uxtah(machInst, rd, rn, rm, rotation); + } + case 0x2: + if (rn == 0xf) { + return new Sxtb16(machInst, rd, rotation, rm); + } else { + return new Sxtab16(machInst, rd, rn, rm, rotation); + } + case 0x3: + if (rn == 0xf) { + return new Uxtb16(machInst, rd, rotation, rm); + } else { + return new Uxtab16(machInst, rd, rn, rm, rotation); + } + case 0x4: + if (rn == 0xf) { + return new Sxtb(machInst, rd, rotation, rm); + } else { + return new Sxtab(machInst, rd, rn, rm, rotation); + } + case 0x5: + if (rn == 0xf) { + return new Uxtb(machInst, rd, rotation, rm); + } else { + return new Uxtab(machInst, rd, rn, rm, rotation); + } + default: + return new Unknown(machInst); + } + } + } else { + if (bits(op2, 3) == 0) { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (bits(op2, 2) == 0x0) { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 5, 4); + switch (op2) { + case 0x0: + switch (op1) { + case 0x1: + return new Sadd16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x2: + return new SasxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x6: + return new SsaxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x5: + return new Ssub16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x0: + return new Sadd8RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x4: + return new Ssub8RegCc(machInst, rd, + rn, rm, 0, LSL); + } + break; + case 0x1: + switch (op1) { + case 0x1: + return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new QasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new QsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op1) { + case 0x1: + return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new ShasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new ShsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } else { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 5, 4); + switch (op2) { + case 0x0: + switch (op1) { + case 0x1: + return new Uadd16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x2: + return new UasxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x6: + return new UsaxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x5: + return new Usub16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x0: + return new Uadd8RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x4: + return new Usub8RegCc(machInst, rd, + rn, rm, 0, LSL); + } + break; + case 0x1: + switch (op1) { + case 0x1: + return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UqasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new UqsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op1) { + case 0x1: + return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UhasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new UhsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } + } else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) { + const uint32_t op1 = bits(machInst, 21, 20); + const uint32_t op2 = bits(machInst, 5, 4); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (op1) { + case 0x0: + switch (op2) { + case 0x0: + return new QaddRegCc(machInst, rd, + rm, rn, 0, LSL); + case 0x1: + return new QdaddRegCc(machInst, rd, + rm, rn, 0, LSL); + case 0x2: + return new QsubRegCc(machInst, rd, + rm, rn, 0, LSL); + case 0x3: + return new QdsubRegCc(machInst, rd, + rm, rn, 0, LSL); + } + break; + case 0x1: + switch (op2) { + case 0x0: + return new Rev(machInst, rd, rn); + case 0x1: + return new Rev16(machInst, rd, rn); + case 0x2: + return new Rbit(machInst, rd, rm); + case 0x3: + return new Revsh(machInst, rd, rn); + } + break; + case 0x2: + if (op2 == 0) { + return new Sel(machInst, rd, rn, rm); + } + break; + case 0x3: + if (op2 == 0) { + return new Clz(machInst, rd, rm); + } + } + } + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb16ShiftAddSubMoveCmp() {{ + decode_block = ''' + { + const uint32_t imm5 = bits(machInst, 10, 6); + const uint32_t imm3 = bits(machInst, 8, 6); + const uint32_t imm8 = bits(machInst, 7, 0); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6); + switch (bits(machInst, 13, 11)) { + case 0x0: // lsl + if (machInst.itstateMask) { + return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL); + } else { + return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL); + } + case 0x1: // lsr + if (machInst.itstateMask) { + return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR); + } else { + return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR); + } + case 0x2: // asr + if (machInst.itstateMask) { + return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR); + } else { + return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR); + } + case 0x3: + switch (bits(machInst, 10, 9)) { + case 0x0: + if (machInst.itstateMask) { + return new AddReg(machInst, rd, rn, rm, 0, LSL); + } else { + return new AddRegCc(machInst, rd, rn, rm, 0, LSL); + } + case 0x1: + if (machInst.itstateMask) { + return new SubReg(machInst, rd, rn, rm, 0, LSL); + } else { + return new SubRegCc(machInst, rd, rn, rm, 0, LSL); + } + case 0x2: + if (machInst.itstateMask) { + return new AddImm(machInst, rd, rn, imm3, true); + } else { + return new AddImmCc(machInst, rd, rn, imm3, true); + } + case 0x3: + if (machInst.itstateMask) { + return new SubImm(machInst, rd, rn, imm3, true); + } else { + return new SubImmCc(machInst, rd, rn, imm3, true); + } + } + case 0x4: + if (machInst.itstateMask) { + return new MovImm(machInst, rd8, INTREG_ZERO, imm8, false); + } else { + return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false); + } + case 0x5: + return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true); + case 0x6: + if (machInst.itstateMask) { + return new AddImm(machInst, rd8, rd8, imm8, true); + } else { + return new AddImmCc(machInst, rd8, rd8, imm8, true); + } + case 0x7: + if (machInst.itstateMask) { + return new SubImm(machInst, rd8, rd8, imm8, true); + } else { + return new SubImmCc(machInst, rd8, rd8, imm8, true); + } + } + } + ''' +}}; + +def format Thumb16DataProcessing() {{ + decode_block = ''' + { + const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + switch (bits(machInst, 9, 6)) { + case 0x0: + if (machInst.itstateMask) { + return new AndReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x1: + if (machInst.itstateMask) { + return new EorReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x2: //lsl + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, LSL); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, LSL); + } + case 0x3: //lsr + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, LSR); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, LSR); + } + case 0x4: //asr + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, ASR); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, ASR); + } + case 0x5: + if (machInst.itstateMask) { + return new AdcReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x6: + if (machInst.itstateMask) { + return new SbcReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x7: // ror + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, ROR); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, ROR); + } + case 0x8: + return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0x9: + if (machInst.itstateMask) { + return new RsbImm(machInst, rdn, rm, 0, true); + } else { + return new RsbImmCc(machInst, rdn, rm, 0, true); + } + case 0xa: + return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0xb: + return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0xc: + if (machInst.itstateMask) { + return new OrrReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0xd: + if (machInst.itstateMask) { + return new Mul(machInst, rdn, rm, rdn); + } else { + return new MulCc(machInst, rdn, rm, rdn); + } + case 0xe: + if (machInst.itstateMask) { + return new BicReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0xf: + if (machInst.itstateMask) { + return new MvnReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + } else { + return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + } + } + } + ''' +}}; + +def format Thumb16SpecDataAndBx() {{ + decode_block = ''' + { + const IntRegIndex rdn = + (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) | + (bits(machInst, 7) << 3)); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3); + switch (bits(machInst, 9, 8)) { + case 0x0: + return new AddReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x1: + return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0x2: + return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + case 0x3: + if (bits(machInst, 7) == 0) { + return new BxReg(machInst, + (IntRegIndex)(uint32_t)bits(machInst, 6, 3), + COND_UC); + } else { + return new BlxReg(machInst, + (IntRegIndex)(uint32_t)bits(machInst, 6, 3), + COND_UC); + } + } + } + ''' +}}; + +def format Thumb16Adr() {{ + decode_block = ''' + { + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const uint32_t imm8 = bits(machInst, 7, 0) << 2; + return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false); + } + ''' +}}; + +def format Thumb16AddSp() {{ + decode_block = ''' + { + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const uint32_t imm8 = bits(machInst, 7, 0) << 2; + return new AddImm(machInst, rd, INTREG_SP, imm8, true); + } + ''' +}}; + +def format ArmMisc() {{ + decode_block = ''' + { + const uint32_t unrotated = bits(machInst, 7, 0); + const uint32_t rotation = (bits(machInst, 11, 8) << 1); + const uint32_t imm = rotate_imm(unrotated, rotation); + const uint8_t byteMask = bits(machInst, 19, 16); + switch (OPCODE) { + case 0x8: + return new MovImm(machInst, (IntRegIndex)(uint32_t)RD, + (IntRegIndex)INTREG_ZERO, + bits(machInst, 11, 0) | (bits(machInst, 19, 16) << 12), + false); + case 0x9: + if (RN == 0) { + switch (IMM) { + case 0x0: + return new NopInst(machInst); + case 0x1: + return new YieldInst(machInst); + case 0x2: + return new WfeInst(machInst); + case 0x3: + return new WfiInst(machInst); + case 0x4: + return new SevInst(machInst); + default: + return new Unknown(machInst); + } + } else { + return new MsrCpsrImm(machInst, imm, byteMask); + } + case 0xa: + { + const uint32_t timm = (bits(machInst, 19, 16) << 12) | + bits(machInst, 11, 0); + return new MovtImm(machInst, (IntRegIndex)(uint32_t)RD, + (IntRegIndex)(uint32_t)RD, timm, true); + } + case 0xb: + return new MsrSpsrImm(machInst, imm, byteMask); + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb16Misc() {{ + decode_block = ''' + { + switch (bits(machInst, 11, 8)) { + case 0x0: + if (bits(machInst, 7)) { + return new SubImm(machInst, INTREG_SP, INTREG_SP, + bits(machInst, 6, 0) << 2, true); + } else { + return new AddImm(machInst, INTREG_SP, INTREG_SP, + bits(machInst, 6, 0) << 2, true); + } + case 0x2: + { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + switch (bits(machInst, 7, 6)) { + case 0x0: + return new Sxth(machInst, rd, 0, rm); + case 0x1: + return new Sxtb(machInst, rd, 0, rm); + case 0x2: + return new Uxth(machInst, rd, 0, rm); + case 0x3: + return new Uxtb(machInst, rd, 0, rm); + } + } + case 0x1: + case 0x3: + return new Cbz(machInst, + (bits(machInst, 9) << 6) | + (bits(machInst, 7, 3) << 1), + (IntRegIndex)(uint32_t)bits(machInst, 2, 0)); + case 0x4: + case 0x5: + { + const uint32_t m = bits(machInst, 8); + const uint32_t regList = bits(machInst, 7, 0) | (m << 14); + return new LdmStm(machInst, INTREG_SP, false, false, false, + true, false, regList); + } + case 0x6: + { + const uint32_t opBits = bits(machInst, 7, 5); + if (opBits == 2) { + return new Setend(machInst, bits(machInst, 3)); + } else if (opBits == 3) { + const bool enable = (bits(machInst, 4) == 0); + const uint32_t mods = (bits(machInst, 2, 0) << 5) | + ((enable ? 1 : 0) << 9); + return new Cps(machInst, mods); + } + } + case 0xa: + { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + switch (bits(machInst, 7, 6)) { + case 0x0: + return new Rev(machInst, rd, rm); + case 0x1: + return new Rev16(machInst, rd, rm); + case 0x3: + return new Revsh(machInst, rd, rm); + default: + break; + } + } + break; + case 0x9: + case 0xb: + return new Cbnz(machInst, + (bits(machInst, 9) << 6) | + (bits(machInst, 7, 3) << 1), + (IntRegIndex)(uint32_t)bits(machInst, 2, 0)); + case 0xc: + case 0xd: + { + const uint32_t p = bits(machInst, 8); + const uint32_t regList = bits(machInst, 7, 0) | (p << 15); + return new LdmStm(machInst, INTREG_SP, true, true, false, + true, true, regList); + } + case 0xe: + return new BkptInst(machInst); + case 0xf: + if (bits(machInst, 3, 0) != 0) + return new ItInst(machInst); + switch (bits(machInst, 7, 4)) { + case 0x0: + return new NopInst(machInst); + case 0x1: + return new YieldInst(machInst); + case 0x2: + return new WfeInst(machInst); + case 0x3: + return new WfiInst(machInst); + case 0x4: + return new SevInst(machInst); + default: + return new WarnUnimplemented("unallocated_hint", machInst); + } + default: + break; + } + return new Unknown(machInst); + } + ''' +}}; + +def format Thumb32DataProcModImm() {{ + + def decInst(mnem, dest="rd", op1="rn"): + return ''' + if (s) { + return new %(mnem)sImmCc(machInst, %(dest)s, + %(op1)s, imm, rotC); + } else { + return new %(mnem)sImm(machInst, %(dest)s, + %(op1)s, imm, rotC); + } + ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1} + + decode_block = ''' + { + const uint32_t op = bits(machInst, 24, 21); + const bool s = (bits(machInst, 20) == 1); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 | + bits(machInst, 14, 12); + const bool rotC = ctrlImm > 3; + const uint32_t dataImm = bits(machInst, 7, 0); + const uint32_t imm = modified_imm(ctrlImm, dataImm); + switch (op) { + case 0x0: + if (rd == INTREG_PC) { + %(tst)s + } else { + %(and)s + } + case 0x1: + %(bic)s + case 0x2: + if (rn == INTREG_PC) { + %(mov)s + } else { + %(orr)s + } + case 0x3: + if (rn == INTREG_PC) { + %(mvn)s + } else { + %(orn)s + } + case 0x4: + if (rd == INTREG_PC) { + %(teq)s + } else { + %(eor)s + } + case 0x8: + if (rd == INTREG_PC) { + %(cmn)s + } else { + %(add)s + } + case 0xa: + %(adc)s + case 0xb: + %(sbc)s + case 0xd: + if (rd == INTREG_PC) { + %(cmp)s + } else { + %(sub)s + } + case 0xe: + %(rsb)s + default: + return new Unknown(machInst); + } + } + ''' % { + "tst" : decInst("Tst", "INTREG_ZERO"), + "and" : decInst("And"), + "bic" : decInst("Bic"), + "mov" : decInst("Mov", op1="INTREG_ZERO"), + "orr" : decInst("Orr"), + "mvn" : decInst("Mvn", op1="INTREG_ZERO"), + "orn" : decInst("Orn"), + "teq" : decInst("Teq", dest="INTREG_ZERO"), + "eor" : decInst("Eor"), + "cmn" : decInst("Cmn", dest="INTREG_ZERO"), + "add" : decInst("Add"), + "adc" : decInst("Adc"), + "sbc" : decInst("Sbc"), + "cmp" : decInst("Cmp", dest="INTREG_ZERO"), + "sub" : decInst("Sub"), + "rsb" : decInst("Rsb") + } +}}; + +def format Thumb32DataProcPlainBin() {{ + decode_block = ''' + { + const uint32_t op = bits(machInst, 24, 20); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + switch (op) { + case 0x0: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11); + if (rn == 0xf) { + return new AdrImm(machInst, rd, (IntRegIndex)1, + imm, false); + } else { + return new AddImm(machInst, rd, rn, imm, true); + } + } + case 0x4: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11) | + (bits(machInst, 19, 16) << 12); + return new MovImm(machInst, rd, INTREG_ZERO, imm, true); + } + case 0xa: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11); + if (rn == 0xf) { + return new AdrImm(machInst, rd, (IntRegIndex)0, + imm, false); + } else { + return new SubImm(machInst, rd, rn, imm, true); + } + } + case 0xc: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11) | + (bits(machInst, 19, 16) << 12); + return new MovtImm(machInst, rd, rd, imm, true); + } + case 0x12: + if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) { + const uint32_t satImm = bits(machInst, 4, 0); + return new Ssat16(machInst, rd, satImm + 1, rn); + } + // Fall through on purpose... + case 0x10: + { + const uint32_t satImm = bits(machInst, 4, 0); + const uint32_t imm = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const ArmShiftType type = + (ArmShiftType)(uint32_t)bits(machInst, 21, 20); + return new Ssat(machInst, rd, satImm + 1, rn, imm, type); + } + case 0x14: + { + const uint32_t lsb = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const uint32_t msb = lsb + bits(machInst, 4, 0); + return new Sbfx(machInst, rd, rn, lsb, msb); + } + case 0x16: + { + const uint32_t lsb = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const uint32_t msb = bits(machInst, 4, 0); + if (rn == 0xf) { + return new Bfc(machInst, rd, rd, lsb, msb); + } else { + return new Bfi(machInst, rd, rn, lsb, msb); + } + } + case 0x1a: + if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) { + const uint32_t satImm = bits(machInst, 4, 0); + return new Usat16(machInst, rd, satImm, rn); + } + // Fall through on purpose... + case 0x18: + { + const uint32_t satImm = bits(machInst, 4, 0); + const uint32_t imm = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const ArmShiftType type = + (ArmShiftType)(uint32_t)bits(machInst, 21, 20); + return new Usat(machInst, rd, satImm, rn, imm, type); + } + case 0x1c: + { + const uint32_t lsb = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const uint32_t msb = lsb + bits(machInst, 4, 0); + return new Ubfx(machInst, rd, rn, lsb, msb); + } + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb32DataProcShiftReg() {{ + + def decInst(mnem, dest="rd", op1="rn"): + return ''' + if (s) { + return new %(mnem)sRegCc(machInst, %(dest)s, + %(op1)s, rm, amt, type); + } else { + return new %(mnem)sReg(machInst, %(dest)s, + %(op1)s, rm, amt, type); + } + ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1} + + decode_block = ''' + { + const uint32_t op = bits(machInst, 24, 21); + const bool s = (bits(machInst, 20) == 1); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t amt = (bits(machInst, 14, 12) << 2) | + bits(machInst, 7, 6); + const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4); + switch (op) { + case 0x0: + if (rd == INTREG_PC) { + %(tst)s + } else { + %(and)s + } + case 0x1: + %(bic)s + case 0x2: + if (rn == INTREG_PC) { + %(mov)s + } else { + %(orr)s + } + case 0x3: + if (rn == INTREG_PC) { + %(mvn)s + } else { + %(orn)s + } + case 0x4: + if (rd == INTREG_PC) { + %(teq)s + } else { + %(eor)s + } + case 0x6: + if (type) { + return new PkhtbReg(machInst, rd, rn, rm, amt, type); + } else { + return new PkhbtReg(machInst, rd, rn, rm, amt, type); + } + case 0x8: + if (rd == INTREG_PC) { + %(cmn)s + } else { + %(add)s + } + case 0xa: + %(adc)s + case 0xb: + %(sbc)s + case 0xd: + if (rd == INTREG_PC) { + %(cmp)s + } else { + %(sub)s + } + case 0xe: + %(rsb)s + default: + return new Unknown(machInst); + } + } + ''' % { + "tst" : decInst("Tst", "INTREG_ZERO"), + "and" : decInst("And"), + "bic" : decInst("Bic"), + "mov" : decInst("Mov", op1="INTREG_ZERO"), + "orr" : decInst("Orr"), + "mvn" : decInst("Mvn", op1="INTREG_ZERO"), + "orn" : decInst("Orn"), + "teq" : decInst("Teq", "INTREG_ZERO"), + "eor" : decInst("Eor"), + "cmn" : decInst("Cmn", "INTREG_ZERO"), + "add" : decInst("Add"), + "adc" : decInst("Adc"), + "sbc" : decInst("Sbc"), + "cmp" : decInst("Cmp", "INTREG_ZERO"), + "sub" : decInst("Sub"), + "rsb" : decInst("Rsb") + } +}}; diff --git a/simulators/gem5/src/arch/arm/isa/formats/formats.isa b/simulators/gem5/src/arch/arm/isa/formats/formats.isa new file mode 100644 index 00000000..90144c10 --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/formats/formats.isa @@ -0,0 +1,84 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +//Templates from this format are used later +//Include the basic format +##include "basic.isa" + +//Include support for predicated instructions +##include "pred.isa" + +//Include the float formats +##include "fp.isa" + +//Include the mem format +##include "mem.isa" + +//Include the macro-mem format +##include "macromem.isa" + +//Include the branch format +##include "branch.isa" + +//Miscellaneous instructions that don't fit elsewhere +##include "misc.isa" + +//Include the unimplemented format +##include "unimp.isa" + +//Include the unknown format +##include "unknown.isa" + +//Include the breakpoint format +##include "breakpoint.isa" + +//Include the formats for data processing instructions +##include "data.isa" + +//Include the formats for multiply instructions +##include "mult.isa" + +//Unconditional instructions +##include "uncond.isa" + +//M5 Psuedo-ops +##include "m5ops.isa" diff --git a/simulators/gem5/src/arch/arm/isa/formats/fp.isa b/simulators/gem5/src/arch/arm/isa/formats/fp.isa new file mode 100644 index 00000000..0cb27d7f --- /dev/null +++ b/simulators/gem5/src/arch/arm/isa/formats/fp.isa @@ -0,0 +1,2507 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2007-2008 The Florida State University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Floating Point operate instructions +// + +output header {{ + + template