merge code
This commit is contained in:
commit
db79945ad0
12 changed files with 707 additions and 663 deletions
|
@ -394,7 +394,7 @@ if main['GCC'] + main['SUNCC'] + main['ICC'] > 1:
|
||||||
if main['GCC']:
|
if main['GCC']:
|
||||||
main.Append(CCFLAGS='-pipe')
|
main.Append(CCFLAGS='-pipe')
|
||||||
main.Append(CCFLAGS='-fno-strict-aliasing')
|
main.Append(CCFLAGS='-fno-strict-aliasing')
|
||||||
main.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
|
main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef'])
|
||||||
main.Append(CXXFLAGS='-Wno-deprecated')
|
main.Append(CXXFLAGS='-Wno-deprecated')
|
||||||
elif main['ICC']:
|
elif main['ICC']:
|
||||||
pass #Fix me... add warning flags once we clean up icc warnings
|
pass #Fix me... add warning flags once we clean up icc warnings
|
||||||
|
|
361
src/SConscript
361
src/SConscript
|
@ -29,6 +29,7 @@
|
||||||
# Authors: Nathan Binkert
|
# Authors: Nathan Binkert
|
||||||
|
|
||||||
import array
|
import array
|
||||||
|
import bisect
|
||||||
import imp
|
import imp
|
||||||
import marshal
|
import marshal
|
||||||
import os
|
import os
|
||||||
|
@ -50,122 +51,144 @@ Export('env')
|
||||||
|
|
||||||
build_env = dict([(opt, env[opt]) for opt in export_vars])
|
build_env = dict([(opt, env[opt]) for opt in export_vars])
|
||||||
|
|
||||||
def sort_list(_list):
|
########################################################################
|
||||||
"""return a sorted copy of '_list'"""
|
# Code for adding source files of various types
|
||||||
if isinstance(_list, list):
|
#
|
||||||
_list = _list[:]
|
class SourceMeta(type):
|
||||||
else:
|
def __init__(cls, name, bases, dict):
|
||||||
_list = list(_list)
|
super(SourceMeta, cls).__init__(name, bases, dict)
|
||||||
_list.sort()
|
cls.all = []
|
||||||
return _list
|
|
||||||
|
|
||||||
class PySourceFile(object):
|
def get(cls, **kwargs):
|
||||||
|
for src in cls.all:
|
||||||
|
for attr,value in kwargs.iteritems():
|
||||||
|
if getattr(src, attr) != value:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
yield src
|
||||||
|
|
||||||
|
class SourceFile(object):
|
||||||
|
__metaclass__ = SourceMeta
|
||||||
|
def __init__(self, source):
|
||||||
|
tnode = source
|
||||||
|
if not isinstance(source, SCons.Node.FS.File):
|
||||||
|
tnode = File(source)
|
||||||
|
|
||||||
|
self.tnode = tnode
|
||||||
|
self.snode = tnode.srcnode()
|
||||||
|
self.filename = str(tnode)
|
||||||
|
self.dirname = dirname(self.filename)
|
||||||
|
self.basename = basename(self.filename)
|
||||||
|
index = self.basename.rfind('.')
|
||||||
|
if index <= 0:
|
||||||
|
# dot files aren't extensions
|
||||||
|
self.extname = self.basename, None
|
||||||
|
else:
|
||||||
|
self.extname = self.basename[:index], self.basename[index+1:]
|
||||||
|
|
||||||
|
for base in type(self).__mro__:
|
||||||
|
if issubclass(base, SourceFile):
|
||||||
|
bisect.insort_right(base.all, self)
|
||||||
|
|
||||||
|
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, bin_only=False,
|
||||||
|
skip_lib=False):
|
||||||
|
super(Source, self).__init__(source)
|
||||||
|
|
||||||
|
self.Werror = Werror
|
||||||
|
self.swig = swig
|
||||||
|
self.bin_only = bin_only
|
||||||
|
self.skip_lib = bin_only or skip_lib
|
||||||
|
|
||||||
|
class PySource(SourceFile):
|
||||||
|
'''Add a python source file to the named package'''
|
||||||
invalid_sym_char = re.compile('[^A-z0-9_]')
|
invalid_sym_char = re.compile('[^A-z0-9_]')
|
||||||
def __init__(self, package, tnode):
|
modules = {}
|
||||||
snode = tnode.srcnode()
|
tnodes = {}
|
||||||
filename = str(tnode)
|
symnames = {}
|
||||||
pyname = basename(filename)
|
|
||||||
assert pyname.endswith('.py')
|
def __init__(self, package, source):
|
||||||
name = pyname[:-3]
|
super(PySource, self).__init__(source)
|
||||||
|
|
||||||
|
modname,ext = self.extname
|
||||||
|
assert ext == 'py'
|
||||||
|
|
||||||
if package:
|
if package:
|
||||||
path = package.split('.')
|
path = package.split('.')
|
||||||
else:
|
else:
|
||||||
path = []
|
path = []
|
||||||
|
|
||||||
modpath = path[:]
|
modpath = path[:]
|
||||||
if name != '__init__':
|
if modname != '__init__':
|
||||||
modpath += [name]
|
modpath += [ modname ]
|
||||||
modpath = '.'.join(modpath)
|
modpath = '.'.join(modpath)
|
||||||
|
|
||||||
arcpath = path + [ pyname ]
|
arcpath = path + [ self.basename ]
|
||||||
arcname = joinpath(*arcpath)
|
debugname = self.snode.abspath
|
||||||
|
|
||||||
debugname = snode.abspath
|
|
||||||
if not exists(debugname):
|
if not exists(debugname):
|
||||||
debugname = tnode.abspath
|
debugname = self.tnode.abspath
|
||||||
|
|
||||||
self.tnode = tnode
|
|
||||||
self.snode = snode
|
|
||||||
self.pyname = pyname
|
|
||||||
self.package = package
|
self.package = package
|
||||||
|
self.modname = modname
|
||||||
self.modpath = modpath
|
self.modpath = modpath
|
||||||
self.arcname = arcname
|
self.arcname = joinpath(*arcpath)
|
||||||
self.debugname = debugname
|
self.debugname = debugname
|
||||||
self.compiled = File(filename + 'c')
|
self.compiled = File(self.filename + 'c')
|
||||||
self.assembly = File(filename + '.s')
|
self.assembly = File(self.filename + '.s')
|
||||||
self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath)
|
self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath)
|
||||||
|
|
||||||
|
PySource.modules[modpath] = self
|
||||||
|
PySource.tnodes[self.tnode] = self
|
||||||
|
PySource.symnames[self.symname] = self
|
||||||
|
|
||||||
########################################################################
|
class SimObject(PySource):
|
||||||
# Code for adding source files of various types
|
|
||||||
#
|
|
||||||
cc_lib_sources = []
|
|
||||||
def Source(source):
|
|
||||||
'''Add a source file to the libm5 build'''
|
|
||||||
if not isinstance(source, SCons.Node.FS.File):
|
|
||||||
source = File(source)
|
|
||||||
|
|
||||||
cc_lib_sources.append(source)
|
|
||||||
|
|
||||||
cc_bin_sources = []
|
|
||||||
def BinSource(source):
|
|
||||||
'''Add a source file to the m5 binary build'''
|
|
||||||
if not isinstance(source, SCons.Node.FS.File):
|
|
||||||
source = File(source)
|
|
||||||
|
|
||||||
cc_bin_sources.append(source)
|
|
||||||
|
|
||||||
py_sources = []
|
|
||||||
def PySource(package, source):
|
|
||||||
'''Add a python source file to the named package'''
|
|
||||||
if not isinstance(source, SCons.Node.FS.File):
|
|
||||||
source = File(source)
|
|
||||||
|
|
||||||
source = PySourceFile(package, source)
|
|
||||||
py_sources.append(source)
|
|
||||||
|
|
||||||
sim_objects_fixed = False
|
|
||||||
sim_object_modfiles = set()
|
|
||||||
def SimObject(source):
|
|
||||||
'''Add a SimObject python file as a python source object and add
|
'''Add a SimObject python file as a python source object and add
|
||||||
it to a list of sim object modules'''
|
it to a list of sim object modules'''
|
||||||
|
|
||||||
if sim_objects_fixed:
|
fixed = False
|
||||||
|
modnames = []
|
||||||
|
|
||||||
|
def __init__(self, source):
|
||||||
|
super(SimObject, self).__init__('m5.objects', source)
|
||||||
|
if self.fixed:
|
||||||
raise AttributeError, "Too late to call SimObject now."
|
raise AttributeError, "Too late to call SimObject now."
|
||||||
|
|
||||||
if not isinstance(source, SCons.Node.FS.File):
|
bisect.insort_right(SimObject.modnames, self.modname)
|
||||||
source = File(source)
|
|
||||||
|
|
||||||
PySource('m5.objects', source)
|
class SwigSource(SourceFile):
|
||||||
modfile = basename(str(source))
|
|
||||||
assert modfile.endswith('.py')
|
|
||||||
modname = modfile[:-3]
|
|
||||||
sim_object_modfiles.add(modname)
|
|
||||||
|
|
||||||
swig_sources = []
|
|
||||||
def SwigSource(package, source):
|
|
||||||
'''Add a swig file to build'''
|
'''Add a swig file to build'''
|
||||||
if not isinstance(source, SCons.Node.FS.File):
|
|
||||||
source = File(source)
|
def __init__(self, package, source):
|
||||||
val = source,package
|
super(SwigSource, self).__init__(source)
|
||||||
swig_sources.append(val)
|
|
||||||
|
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)
|
||||||
|
self.py_source = PySource(package, py_file)
|
||||||
|
|
||||||
unit_tests = []
|
unit_tests = []
|
||||||
def UnitTest(target, sources):
|
def UnitTest(target, sources):
|
||||||
if not isinstance(sources, (list, tuple)):
|
if not isinstance(sources, (list, tuple)):
|
||||||
sources = [ sources ]
|
sources = [ sources ]
|
||||||
|
|
||||||
srcs = []
|
sources = [ Source(src, skip_lib=True) for src in sources ]
|
||||||
for source in sources:
|
unit_tests.append((target, sources))
|
||||||
if not isinstance(source, SCons.Node.FS.File):
|
|
||||||
source = File(source)
|
|
||||||
srcs.append(source)
|
|
||||||
|
|
||||||
unit_tests.append((target, srcs))
|
|
||||||
|
|
||||||
# Children should have access
|
# Children should have access
|
||||||
Export('Source')
|
Export('Source')
|
||||||
Export('BinSource')
|
|
||||||
Export('PySource')
|
Export('PySource')
|
||||||
Export('SimObject')
|
Export('SimObject')
|
||||||
Export('SwigSource')
|
Export('SwigSource')
|
||||||
|
@ -276,7 +299,8 @@ class DictImporter(object):
|
||||||
if fullname.startswith('m5.internal'):
|
if fullname.startswith('m5.internal'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if fullname in self.modules and exists(self.modules[fullname]):
|
source = self.modules.get(fullname, None)
|
||||||
|
if source is not None and exists(source.snode.abspath):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -295,34 +319,28 @@ class DictImporter(object):
|
||||||
mod.__dict__['buildEnv'] = build_env
|
mod.__dict__['buildEnv'] = build_env
|
||||||
return mod
|
return mod
|
||||||
|
|
||||||
srcfile = self.modules[fullname]
|
source = self.modules[fullname]
|
||||||
if basename(srcfile) == '__init__.py':
|
if source.modname == '__init__':
|
||||||
mod.__path__ = fullname.split('.')
|
mod.__path__ = source.modpath
|
||||||
mod.__file__ = srcfile
|
mod.__file__ = source.snode.abspath
|
||||||
|
|
||||||
exec file(srcfile, 'r') in mod.__dict__
|
exec file(source.snode.abspath, 'r') in mod.__dict__
|
||||||
|
|
||||||
return mod
|
return mod
|
||||||
|
|
||||||
py_modules = {}
|
|
||||||
for source in py_sources:
|
|
||||||
py_modules[source.modpath] = source.snode.abspath
|
|
||||||
|
|
||||||
# install the python importer so we can grab stuff from the source
|
# install the python importer so we can grab stuff from the source
|
||||||
# tree itself. We can't have SimObjects added after this point or
|
# 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.
|
# else we won't know about them for the rest of the stuff.
|
||||||
sim_objects_fixed = True
|
SimObject.fixed = True
|
||||||
importer = DictImporter(py_modules)
|
importer = DictImporter(PySource.modules)
|
||||||
sys.meta_path[0:0] = [ importer ]
|
sys.meta_path[0:0] = [ importer ]
|
||||||
|
|
||||||
import m5
|
import m5
|
||||||
|
|
||||||
# import all sim objects so we can populate the all_objects list
|
# 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
|
# make sure that we're working with a list, then let's sort it
|
||||||
sim_objects = list(sim_object_modfiles)
|
for modname in SimObject.modnames:
|
||||||
sim_objects.sort()
|
exec('from m5.objects import %s' % modname)
|
||||||
for simobj in sim_objects:
|
|
||||||
exec('from m5.objects import %s' % simobj)
|
|
||||||
|
|
||||||
# we need to unload all of the currently imported modules so that they
|
# we need to unload all of the currently imported modules so that they
|
||||||
# will be re-imported the next time the sconscript is run
|
# will be re-imported the next time the sconscript is run
|
||||||
|
@ -333,7 +351,7 @@ sim_objects = m5.SimObject.allClasses
|
||||||
all_enums = m5.params.allEnums
|
all_enums = m5.params.allEnums
|
||||||
|
|
||||||
all_params = {}
|
all_params = {}
|
||||||
for name,obj in sim_objects.iteritems():
|
for name,obj in sorted(sim_objects.iteritems()):
|
||||||
for param in obj._params.local.values():
|
for param in obj._params.local.values():
|
||||||
if not hasattr(param, 'swig_decl'):
|
if not hasattr(param, 'swig_decl'):
|
||||||
continue
|
continue
|
||||||
|
@ -346,7 +364,7 @@ for name,obj in sim_objects.iteritems():
|
||||||
# calculate extra dependencies
|
# calculate extra dependencies
|
||||||
#
|
#
|
||||||
module_depends = ["m5", "m5.SimObject", "m5.params"]
|
module_depends = ["m5", "m5.SimObject", "m5.params"]
|
||||||
depends = [ File(py_modules[dep]) for dep in module_depends ]
|
depends = [ PySource.modules[dep].tnode for dep in module_depends ]
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
#
|
#
|
||||||
|
@ -392,7 +410,7 @@ def makeObjectsInitFile(target, source, env):
|
||||||
|
|
||||||
# Generate an __init__.py file for the objects package
|
# Generate an __init__.py file for the objects package
|
||||||
env.Command('python/m5/objects/__init__.py',
|
env.Command('python/m5/objects/__init__.py',
|
||||||
[ Value(o) for o in sort_list(sim_object_modfiles) ],
|
map(Value, SimObject.modnames),
|
||||||
makeObjectsInitFile)
|
makeObjectsInitFile)
|
||||||
PySource('m5.objects', 'python/m5/objects/__init__.py')
|
PySource('m5.objects', 'python/m5/objects/__init__.py')
|
||||||
|
|
||||||
|
@ -409,6 +427,7 @@ def createSimObjectParam(target, source, env):
|
||||||
obj = sim_objects[name]
|
obj = sim_objects[name]
|
||||||
|
|
||||||
print >>hh_file, obj.cxx_decl()
|
print >>hh_file, obj.cxx_decl()
|
||||||
|
hh_file.close()
|
||||||
|
|
||||||
def createSwigParam(target, source, env):
|
def createSwigParam(target, source, env):
|
||||||
assert len(target) == 1 and len(source) == 1
|
assert len(target) == 1 and len(source) == 1
|
||||||
|
@ -419,6 +438,7 @@ def createSwigParam(target, source, env):
|
||||||
|
|
||||||
for line in param.swig_decl():
|
for line in param.swig_decl():
|
||||||
print >>i_file, line
|
print >>i_file, line
|
||||||
|
i_file.close()
|
||||||
|
|
||||||
def createEnumStrings(target, source, env):
|
def createEnumStrings(target, source, env):
|
||||||
assert len(target) == 1 and len(source) == 1
|
assert len(target) == 1 and len(source) == 1
|
||||||
|
@ -438,11 +458,13 @@ def createEnumParam(target, source, env):
|
||||||
obj = all_enums[name]
|
obj = all_enums[name]
|
||||||
|
|
||||||
print >>hh_file, obj.cxx_decl()
|
print >>hh_file, obj.cxx_decl()
|
||||||
|
hh_file.close()
|
||||||
|
|
||||||
# Generate all of the SimObject param struct header files
|
# Generate all of the SimObject param struct header files
|
||||||
params_hh_files = []
|
params_hh_files = []
|
||||||
for name,simobj in sim_objects.iteritems():
|
for name,simobj in sorted(sim_objects.iteritems()):
|
||||||
extra_deps = [ File(py_modules[simobj.__module__]) ]
|
py_source = PySource.modules[simobj.__module__]
|
||||||
|
extra_deps = [ py_source.tnode ]
|
||||||
|
|
||||||
hh_file = File('params/%s.hh' % name)
|
hh_file = File('params/%s.hh' % name)
|
||||||
params_hh_files.append(hh_file)
|
params_hh_files.append(hh_file)
|
||||||
|
@ -463,8 +485,9 @@ for name,param in all_params.iteritems():
|
||||||
env.Depends(i_file, depends)
|
env.Depends(i_file, depends)
|
||||||
|
|
||||||
# Generate all enum header files
|
# Generate all enum header files
|
||||||
for name,enum in all_enums.iteritems():
|
for name,enum in sorted(all_enums.iteritems()):
|
||||||
extra_deps = [ File(py_modules[enum.__module__]) ]
|
py_source = PySource.modules[enum.__module__]
|
||||||
|
extra_deps = [ py_source.tnode ]
|
||||||
|
|
||||||
cc_file = File('enums/%s.cc' % name)
|
cc_file = File('enums/%s.cc' % name)
|
||||||
env.Command(cc_file, Value(name), createEnumStrings)
|
env.Command(cc_file, Value(name), createEnumStrings)
|
||||||
|
@ -576,32 +599,18 @@ def buildParams(target, source, env):
|
||||||
print >>out, '%%include "params/%s.hh"' % obj
|
print >>out, '%%include "params/%s.hh"' % obj
|
||||||
|
|
||||||
params_file = File('params/params.i')
|
params_file = File('params/params.i')
|
||||||
names = sort_list(sim_objects.keys())
|
names = sorted(sim_objects.keys())
|
||||||
env.Command(params_file, [ Value(v) for v in names ], buildParams)
|
env.Command(params_file, map(Value, names), buildParams)
|
||||||
env.Depends(params_file, params_hh_files + params_i_files + depends)
|
env.Depends(params_file, params_hh_files + params_i_files + depends)
|
||||||
SwigSource('m5.objects', params_file)
|
SwigSource('m5.objects', params_file)
|
||||||
|
|
||||||
# Build all swig modules
|
# Build all swig modules
|
||||||
swig_modules = []
|
for swig in SwigSource.all:
|
||||||
cc_swig_sources = []
|
env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode,
|
||||||
for source,package in swig_sources:
|
|
||||||
filename = str(source)
|
|
||||||
assert filename.endswith('.i')
|
|
||||||
|
|
||||||
base = '.'.join(filename.split('.')[:-1])
|
|
||||||
module = basename(base)
|
|
||||||
cc_file = base + '_wrap.cc'
|
|
||||||
py_file = base + '.py'
|
|
||||||
|
|
||||||
env.Command([cc_file, py_file], source,
|
|
||||||
'$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
|
'$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
|
||||||
'-o ${TARGETS[0]} $SOURCES')
|
'-o ${TARGETS[0]} $SOURCES')
|
||||||
env.Depends(py_file, source)
|
env.Depends(swig.py_source.tnode, swig.tnode)
|
||||||
env.Depends(cc_file, source)
|
env.Depends(swig.cc_source.tnode, swig.tnode)
|
||||||
|
|
||||||
swig_modules.append(Value(module))
|
|
||||||
cc_swig_sources.append(File(cc_file))
|
|
||||||
PySource(package, py_file)
|
|
||||||
|
|
||||||
# Generate the main swig init file
|
# Generate the main swig init file
|
||||||
def makeSwigInit(target, source, env):
|
def makeSwigInit(target, source, env):
|
||||||
|
@ -616,7 +625,9 @@ def makeSwigInit(target, source, env):
|
||||||
print >>f, '}'
|
print >>f, '}'
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
env.Command('python/swig/init.cc', swig_modules, makeSwigInit)
|
env.Command('python/swig/init.cc',
|
||||||
|
map(Value, sorted(s.module for s in SwigSource.all)),
|
||||||
|
makeSwigInit)
|
||||||
Source('python/swig/init.cc')
|
Source('python/swig/init.cc')
|
||||||
|
|
||||||
# Generate traceflags.py
|
# Generate traceflags.py
|
||||||
|
@ -813,7 +824,7 @@ extern const Flags *compoundFlags[];
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
flags = [ Value(f) for f in trace_flags.values() ]
|
flags = map(Value, trace_flags.values())
|
||||||
env.Command('base/traceflags.py', flags, traceFlagsPy)
|
env.Command('base/traceflags.py', flags, traceFlagsPy)
|
||||||
PySource('m5', 'base/traceflags.py')
|
PySource('m5', 'base/traceflags.py')
|
||||||
|
|
||||||
|
@ -827,10 +838,6 @@ Source('base/traceflags.cc')
|
||||||
# byte code, compress it, and then generate an assembly file that
|
# byte code, compress it, and then generate an assembly file that
|
||||||
# inserts the result into the data section with symbols indicating the
|
# inserts the result into the data section with symbols indicating the
|
||||||
# beginning, and end (and with the size at the end)
|
# beginning, and end (and with the size at the end)
|
||||||
py_sources_tnodes = {}
|
|
||||||
for pysource in py_sources:
|
|
||||||
py_sources_tnodes[pysource.tnode] = pysource
|
|
||||||
|
|
||||||
def objectifyPyFile(target, source, env):
|
def objectifyPyFile(target, source, env):
|
||||||
'''Action function to compile a .py into a code object, marshal
|
'''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
|
it, compress it, and stick it into an asm file so the code appears
|
||||||
|
@ -839,7 +846,7 @@ def objectifyPyFile(target, source, env):
|
||||||
src = file(str(source[0]), 'r').read()
|
src = file(str(source[0]), 'r').read()
|
||||||
dst = file(str(target[0]), 'w')
|
dst = file(str(target[0]), 'w')
|
||||||
|
|
||||||
pysource = py_sources_tnodes[source[0]]
|
pysource = PySource.tnodes[source[0]]
|
||||||
compiled = compile(src, pysource.debugname, 'exec')
|
compiled = compile(src, pysource.debugname, 'exec')
|
||||||
marshalled = marshal.dumps(compiled)
|
marshalled = marshal.dumps(compiled)
|
||||||
compressed = zlib.compress(marshalled)
|
compressed = zlib.compress(marshalled)
|
||||||
|
@ -864,7 +871,7 @@ def objectifyPyFile(target, source, env):
|
||||||
print >>dst, "%s_end:" % sym
|
print >>dst, "%s_end:" % sym
|
||||||
print >>dst, ".long %d" % len(marshalled)
|
print >>dst, ".long %d" % len(marshalled)
|
||||||
|
|
||||||
for source in py_sources:
|
for source in PySource.all:
|
||||||
env.Command(source.assembly, source.tnode, objectifyPyFile)
|
env.Command(source.assembly, source.tnode, objectifyPyFile)
|
||||||
Source(source.assembly)
|
Source(source.assembly)
|
||||||
|
|
||||||
|
@ -873,14 +880,11 @@ for source in py_sources:
|
||||||
# contains information about the importer that python uses to get at
|
# contains information about the importer that python uses to get at
|
||||||
# the embedded files, and then there's a list of all of the rest that
|
# the embedded files, and then there's a list of all of the rest that
|
||||||
# the importer uses to load the rest on demand.
|
# the importer uses to load the rest on demand.
|
||||||
py_sources_symbols = {}
|
|
||||||
for pysource in py_sources:
|
|
||||||
py_sources_symbols[pysource.symname] = pysource
|
|
||||||
def pythonInit(target, source, env):
|
def pythonInit(target, source, env):
|
||||||
dst = file(str(target[0]), 'w')
|
dst = file(str(target[0]), 'w')
|
||||||
|
|
||||||
def dump_mod(sym, endchar=','):
|
def dump_mod(sym, endchar=','):
|
||||||
pysource = py_sources_symbols[sym]
|
pysource = PySource.symnames[sym]
|
||||||
print >>dst, ' { "%s",' % pysource.arcname
|
print >>dst, ' { "%s",' % pysource.arcname
|
||||||
print >>dst, ' "%s",' % pysource.modpath
|
print >>dst, ' "%s",' % pysource.modpath
|
||||||
print >>dst, ' %s_beg, %s_end,' % (sym, sym)
|
print >>dst, ' %s_beg, %s_end,' % (sym, sym)
|
||||||
|
@ -907,8 +911,10 @@ def pythonInit(target, source, env):
|
||||||
print >>dst, " { 0, 0, 0, 0, 0, 0 }"
|
print >>dst, " { 0, 0, 0, 0, 0, 0 }"
|
||||||
print >>dst, "};"
|
print >>dst, "};"
|
||||||
|
|
||||||
symbols = [Value(s.symname) for s in py_sources]
|
|
||||||
env.Command('sim/init_python.cc', symbols, pythonInit)
|
env.Command('sim/init_python.cc',
|
||||||
|
map(Value, (s.symname for s in PySource.all)),
|
||||||
|
pythonInit)
|
||||||
Source('sim/init_python.cc')
|
Source('sim/init_python.cc')
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -920,26 +926,7 @@ Source('sim/init_python.cc')
|
||||||
# List of constructed environments to pass back to SConstruct
|
# List of constructed environments to pass back to SConstruct
|
||||||
envList = []
|
envList = []
|
||||||
|
|
||||||
# This function adds the specified sources to the given build
|
date_source = Source('base/date.cc', skip_lib=True)
|
||||||
# environment, and returns a list of all the corresponding SCons
|
|
||||||
# Object nodes (including an extra one for date.cc). We explicitly
|
|
||||||
# add the Object nodes so we can set up special dependencies for
|
|
||||||
# date.cc.
|
|
||||||
def make_objs(sources, env, static):
|
|
||||||
if static:
|
|
||||||
XObject = env.StaticObject
|
|
||||||
else:
|
|
||||||
XObject = env.SharedObject
|
|
||||||
|
|
||||||
objs = [ XObject(s) for s in sources ]
|
|
||||||
|
|
||||||
# make date.cc depend on all other objects so it always gets
|
|
||||||
# recompiled whenever anything else does
|
|
||||||
date_obj = XObject('base/date.cc')
|
|
||||||
|
|
||||||
env.Depends(date_obj, objs)
|
|
||||||
objs.append(date_obj)
|
|
||||||
return objs
|
|
||||||
|
|
||||||
# Function to create a new build environment as clone of current
|
# Function to create a new build environment as clone of current
|
||||||
# environment 'env' with modified object suffix and optional stripped
|
# environment 'env' with modified object suffix and optional stripped
|
||||||
|
@ -956,15 +943,45 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
|
||||||
new_env.Append(**kwargs)
|
new_env.Append(**kwargs)
|
||||||
|
|
||||||
swig_env = new_env.Clone()
|
swig_env = new_env.Clone()
|
||||||
|
swig_env.Append(CCFLAGS='-Werror')
|
||||||
if env['GCC']:
|
if env['GCC']:
|
||||||
swig_env.Append(CCFLAGS='-Wno-uninitialized')
|
swig_env.Append(CCFLAGS='-Wno-uninitialized')
|
||||||
swig_env.Append(CCFLAGS='-Wno-sign-compare')
|
swig_env.Append(CCFLAGS='-Wno-sign-compare')
|
||||||
swig_env.Append(CCFLAGS='-Wno-parentheses')
|
swig_env.Append(CCFLAGS='-Wno-parentheses')
|
||||||
|
|
||||||
static_objs = make_objs(cc_lib_sources, new_env, static=True)
|
werror_env = new_env.Clone()
|
||||||
shared_objs = make_objs(cc_lib_sources, new_env, static=False)
|
werror_env.Append(CCFLAGS='-Werror')
|
||||||
static_objs += [ swig_env.StaticObject(s) for s in cc_swig_sources ]
|
|
||||||
shared_objs += [ swig_env.SharedObject(s) for s in cc_swig_sources ]
|
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(skip_lib=False)]
|
||||||
|
shared_objs = [ make_obj(s, False) for s in Source.get(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(static_date)
|
||||||
|
|
||||||
# First make a library of everything but main() so other programs can
|
# First make a library of everything but main() so other programs can
|
||||||
# link against m5.
|
# link against m5.
|
||||||
|
@ -972,21 +989,23 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
|
||||||
shared_lib = new_env.SharedLibrary(libname, shared_objs)
|
shared_lib = new_env.SharedLibrary(libname, shared_objs)
|
||||||
|
|
||||||
for target, sources in unit_tests:
|
for target, sources in unit_tests:
|
||||||
objs = [ new_env.StaticObject(s) for s in sources ]
|
objs = [ make_obj(s, static=True) for s in sources ]
|
||||||
new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs)
|
new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs)
|
||||||
|
|
||||||
# Now link a stub with main() and the static library.
|
# Now link a stub with main() and the static library.
|
||||||
objects = [new_env.Object(s) for s in cc_bin_sources] + static_objs
|
bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ]
|
||||||
|
progname = exename
|
||||||
|
if strip:
|
||||||
|
progname += '.unstripped'
|
||||||
|
|
||||||
|
targets = new_env.Program(progname, bin_objs + static_objs)
|
||||||
|
|
||||||
if strip:
|
if strip:
|
||||||
unstripped_exe = exename + '.unstripped'
|
|
||||||
new_env.Program(unstripped_exe, objects)
|
|
||||||
if sys.platform == 'sunos5':
|
if sys.platform == 'sunos5':
|
||||||
cmd = 'cp $SOURCE $TARGET; strip $TARGET'
|
cmd = 'cp $SOURCE $TARGET; strip $TARGET'
|
||||||
else:
|
else:
|
||||||
cmd = 'strip $SOURCE -o $TARGET'
|
cmd = 'strip $SOURCE -o $TARGET'
|
||||||
targets = new_env.Command(exename, unstripped_exe, cmd)
|
targets = new_env.Command(exename, progname, cmd)
|
||||||
else:
|
|
||||||
targets = new_env.Program(exename, objects)
|
|
||||||
|
|
||||||
new_env.M5Binary = targets[0]
|
new_env.M5Binary = targets[0]
|
||||||
envList.append(new_env)
|
envList.append(new_env)
|
||||||
|
|
|
@ -271,12 +271,8 @@ namespace X86ISA
|
||||||
tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
|
tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
|
||||||
tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);
|
tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);
|
||||||
|
|
||||||
// We're now in real mode, effectively at CPL 0
|
// Update the handy M5 Reg.
|
||||||
HandyM5Reg m5Reg = 0;
|
tc->setMiscReg(MISCREG_M5_REG, 0);
|
||||||
m5Reg.mode = LegacyMode;
|
|
||||||
m5Reg.submode = RealMode;
|
|
||||||
m5Reg.cpl = 0;
|
|
||||||
tc->setMiscReg(MISCREG_M5_REG, m5Reg);
|
|
||||||
MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt;
|
MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt;
|
||||||
tc->setMicroPC(romMicroPC(entry));
|
tc->setMicroPC(romMicroPC(entry));
|
||||||
tc->setNextMicroPC(romMicroPC(entry) + 1);
|
tc->setNextMicroPC(romMicroPC(entry) + 1);
|
||||||
|
@ -289,7 +285,7 @@ namespace X86ISA
|
||||||
HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG);
|
HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG);
|
||||||
if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) {
|
if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) {
|
||||||
panic("Startup IPI recived outside of real mode. "
|
panic("Startup IPI recived outside of real mode. "
|
||||||
"Don't know what to do.");
|
"Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode);
|
||||||
}
|
}
|
||||||
|
|
||||||
tc->setMiscReg(MISCREG_CS, vector << 8);
|
tc->setMiscReg(MISCREG_CS, vector << 8);
|
||||||
|
|
|
@ -96,6 +96,64 @@ using namespace std;
|
||||||
|
|
||||||
class Checkpoint;
|
class Checkpoint;
|
||||||
|
|
||||||
|
void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0,
|
||||||
|
SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags)
|
||||||
|
{
|
||||||
|
HandyM5Reg m5reg;
|
||||||
|
if (efer.lma) {
|
||||||
|
m5reg.mode = LongMode;
|
||||||
|
if (csAttr.longMode)
|
||||||
|
m5reg.submode = SixtyFourBitMode;
|
||||||
|
else
|
||||||
|
m5reg.submode = CompatabilityMode;
|
||||||
|
} else {
|
||||||
|
m5reg.mode = LegacyMode;
|
||||||
|
if (cr0.pe) {
|
||||||
|
if (rflags.vm)
|
||||||
|
m5reg.submode = Virtual8086Mode;
|
||||||
|
else
|
||||||
|
m5reg.submode = ProtectedMode;
|
||||||
|
} else {
|
||||||
|
m5reg.submode = RealMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m5reg.cpl = csAttr.dpl;
|
||||||
|
m5reg.paging = cr0.pg;
|
||||||
|
m5reg.prot = cr0.pe;
|
||||||
|
|
||||||
|
// Compute the default and alternate operand size.
|
||||||
|
if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) {
|
||||||
|
m5reg.defOp = 2;
|
||||||
|
m5reg.altOp = 1;
|
||||||
|
} else {
|
||||||
|
m5reg.defOp = 1;
|
||||||
|
m5reg.altOp = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the default and alternate address size.
|
||||||
|
if (m5reg.submode == SixtyFourBitMode) {
|
||||||
|
m5reg.defAddr = 3;
|
||||||
|
m5reg.altAddr = 2;
|
||||||
|
} else if (csAttr.defaultSize) {
|
||||||
|
m5reg.defAddr = 2;
|
||||||
|
m5reg.altAddr = 1;
|
||||||
|
} else {
|
||||||
|
m5reg.defAddr = 1;
|
||||||
|
m5reg.altAddr = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the stack size
|
||||||
|
if (m5reg.submode == SixtyFourBitMode) {
|
||||||
|
m5reg.stack = 3;
|
||||||
|
} else if (ssAttr.defaultSize) {
|
||||||
|
m5reg.stack = 2;
|
||||||
|
} else {
|
||||||
|
m5reg.stack = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
regVal[MISCREG_M5_REG] = m5reg;
|
||||||
|
}
|
||||||
|
|
||||||
void MiscRegFile::clear()
|
void MiscRegFile::clear()
|
||||||
{
|
{
|
||||||
// Blank everything. 0 might not be an appropriate value for some things,
|
// Blank everything. 0 might not be an appropriate value for some things,
|
||||||
|
@ -151,39 +209,17 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
|
||||||
CR0 toggled = regVal[miscReg] ^ val;
|
CR0 toggled = regVal[miscReg] ^ val;
|
||||||
CR0 newCR0 = val;
|
CR0 newCR0 = val;
|
||||||
Efer efer = regVal[MISCREG_EFER];
|
Efer efer = regVal[MISCREG_EFER];
|
||||||
HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
|
|
||||||
if (toggled.pg && efer.lme) {
|
if (toggled.pg && efer.lme) {
|
||||||
if (newCR0.pg) {
|
if (newCR0.pg) {
|
||||||
//Turning on long mode
|
//Turning on long mode
|
||||||
efer.lma = 1;
|
efer.lma = 1;
|
||||||
m5reg.mode = LongMode;
|
|
||||||
regVal[MISCREG_EFER] = efer;
|
regVal[MISCREG_EFER] = efer;
|
||||||
} else {
|
} else {
|
||||||
//Turning off long mode
|
//Turning off long mode
|
||||||
efer.lma = 0;
|
efer.lma = 0;
|
||||||
m5reg.mode = LegacyMode;
|
|
||||||
regVal[MISCREG_EFER] = efer;
|
regVal[MISCREG_EFER] = efer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Figure out what submode we're in.
|
|
||||||
if (m5reg.mode == LongMode) {
|
|
||||||
SegAttr csAttr = regVal[MISCREG_CS_ATTR];
|
|
||||||
if (csAttr.longMode)
|
|
||||||
m5reg.submode = SixtyFourBitMode;
|
|
||||||
else
|
|
||||||
m5reg.submode = CompatabilityMode;
|
|
||||||
} else {
|
|
||||||
if (newCR0.pe) {
|
|
||||||
RFLAGS rflags = regVal[MISCREG_RFLAGS];
|
|
||||||
if (rflags.vm)
|
|
||||||
m5reg.submode = Virtual8086Mode;
|
|
||||||
else
|
|
||||||
m5reg.submode = ProtectedMode;
|
|
||||||
} else {
|
|
||||||
m5reg.submode = RealMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
regVal[MISCREG_M5_REG] = m5reg;
|
|
||||||
if (toggled.pg) {
|
if (toggled.pg) {
|
||||||
tc->getITBPtr()->invalidateAll();
|
tc->getITBPtr()->invalidateAll();
|
||||||
tc->getDTBPtr()->invalidateAll();
|
tc->getDTBPtr()->invalidateAll();
|
||||||
|
@ -191,6 +227,11 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
|
||||||
//This must always be 1.
|
//This must always be 1.
|
||||||
newCR0.et = 1;
|
newCR0.et = 1;
|
||||||
newVal = newCR0;
|
newVal = newCR0;
|
||||||
|
updateHandyM5Reg(regVal[MISCREG_EFER],
|
||||||
|
newCR0,
|
||||||
|
regVal[MISCREG_CS_ATTR],
|
||||||
|
regVal[MISCREG_SS_ATTR],
|
||||||
|
regVal[MISCREG_RFLAGS]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MISCREG_CR2:
|
case MISCREG_CR2:
|
||||||
|
@ -214,28 +255,33 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
|
||||||
{
|
{
|
||||||
SegAttr toggled = regVal[miscReg] ^ val;
|
SegAttr toggled = regVal[miscReg] ^ val;
|
||||||
SegAttr newCSAttr = val;
|
SegAttr newCSAttr = val;
|
||||||
HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
|
|
||||||
if (toggled.longMode) {
|
if (toggled.longMode) {
|
||||||
if (newCSAttr.longMode) {
|
if (newCSAttr.longMode) {
|
||||||
if (m5reg.mode == LongMode)
|
|
||||||
m5reg.submode = SixtyFourBitMode;
|
|
||||||
regVal[MISCREG_ES_EFF_BASE] = 0;
|
regVal[MISCREG_ES_EFF_BASE] = 0;
|
||||||
regVal[MISCREG_CS_EFF_BASE] = 0;
|
regVal[MISCREG_CS_EFF_BASE] = 0;
|
||||||
regVal[MISCREG_SS_EFF_BASE] = 0;
|
regVal[MISCREG_SS_EFF_BASE] = 0;
|
||||||
regVal[MISCREG_DS_EFF_BASE] = 0;
|
regVal[MISCREG_DS_EFF_BASE] = 0;
|
||||||
} else {
|
} else {
|
||||||
if (m5reg.mode == LongMode)
|
|
||||||
m5reg.submode = CompatabilityMode;
|
|
||||||
regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
|
regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
|
||||||
regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
|
regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
|
||||||
regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
|
regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
|
||||||
regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
|
regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m5reg.cpl = newCSAttr.dpl;
|
updateHandyM5Reg(regVal[MISCREG_EFER],
|
||||||
regVal[MISCREG_M5_REG] = m5reg;
|
regVal[MISCREG_CR0],
|
||||||
|
newCSAttr,
|
||||||
|
regVal[MISCREG_SS_ATTR],
|
||||||
|
regVal[MISCREG_RFLAGS]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MISCREG_SS_ATTR:
|
||||||
|
updateHandyM5Reg(regVal[MISCREG_EFER],
|
||||||
|
regVal[MISCREG_CR0],
|
||||||
|
regVal[MISCREG_CS_ATTR],
|
||||||
|
val,
|
||||||
|
regVal[MISCREG_RFLAGS]);
|
||||||
|
break;
|
||||||
// These segments always actually use their bases, or in other words
|
// These segments always actually use their bases, or in other words
|
||||||
// their effective bases must stay equal to their actual bases.
|
// their effective bases must stay equal to their actual bases.
|
||||||
case MISCREG_FS_BASE:
|
case MISCREG_FS_BASE:
|
||||||
|
@ -333,6 +379,16 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
|
||||||
dr7.len3 = newDR7.len3;
|
dr7.len3 = newDR7.len3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MISCREG_M5_REG:
|
||||||
|
// Writing anything to the m5reg with side effects makes it update
|
||||||
|
// based on the current values of the relevant registers. The actual
|
||||||
|
// value written is discarded.
|
||||||
|
updateHandyM5Reg(regVal[MISCREG_EFER],
|
||||||
|
regVal[MISCREG_CR0],
|
||||||
|
regVal[MISCREG_CS_ATTR],
|
||||||
|
regVal[MISCREG_SS_ATTR],
|
||||||
|
regVal[MISCREG_RFLAGS]);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,8 @@ namespace X86ISA
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
MiscReg regVal[NumMiscRegs];
|
MiscReg regVal[NumMiscRegs];
|
||||||
|
void updateHandyM5Reg(Efer efer, CR0 cr0,
|
||||||
|
SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
|
@ -518,6 +518,13 @@ namespace X86ISA
|
||||||
Bitfield<0> mode;
|
Bitfield<0> mode;
|
||||||
Bitfield<3, 1> submode;
|
Bitfield<3, 1> submode;
|
||||||
Bitfield<5, 4> cpl;
|
Bitfield<5, 4> cpl;
|
||||||
|
Bitfield<6> paging;
|
||||||
|
Bitfield<7> prot;
|
||||||
|
Bitfield<9, 8> defOp;
|
||||||
|
Bitfield<11, 10> altOp;
|
||||||
|
Bitfield<13, 12> defAddr;
|
||||||
|
Bitfield<15, 14> altAddr;
|
||||||
|
Bitfield<17, 16> stack;
|
||||||
EndBitUnion(HandyM5Reg)
|
EndBitUnion(HandyM5Reg)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -80,9 +80,9 @@ namespace X86ISA
|
||||||
|
|
||||||
emi.modRM = 0;
|
emi.modRM = 0;
|
||||||
emi.sib = 0;
|
emi.sib = 0;
|
||||||
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
||||||
emi.mode.mode = m5reg.mode;
|
emi.mode.mode = m5Reg.mode;
|
||||||
emi.mode.submode = m5reg.submode;
|
emi.mode.submode = m5Reg.submode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Predecoder::process()
|
void Predecoder::process()
|
||||||
|
@ -216,34 +216,15 @@ namespace X86ISA
|
||||||
DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
|
DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
|
||||||
emi.opcode.op = nextByte;
|
emi.opcode.op = nextByte;
|
||||||
|
|
||||||
SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
|
|
||||||
|
|
||||||
//Figure out the effective operand size. This can be overriden to
|
//Figure out the effective operand size. This can be overriden to
|
||||||
//a fixed value at the decoder level.
|
//a fixed value at the decoder level.
|
||||||
int logOpSize;
|
int logOpSize;
|
||||||
if (emi.mode.submode == SixtyFourBitMode)
|
|
||||||
{
|
|
||||||
if (emi.rex.w)
|
if (emi.rex.w)
|
||||||
logOpSize = 3; // 64 bit operand size
|
logOpSize = 3; // 64 bit operand size
|
||||||
else if (emi.legacy.op)
|
else if (emi.legacy.op)
|
||||||
logOpSize = 1; // 16 bit operand size
|
logOpSize = m5Reg.altOp;
|
||||||
else
|
else
|
||||||
logOpSize = 2; // 32 bit operand size
|
logOpSize = m5Reg.defOp;
|
||||||
}
|
|
||||||
else if(csAttr.defaultSize)
|
|
||||||
{
|
|
||||||
if(emi.legacy.op)
|
|
||||||
logOpSize = 1; // 16 bit operand size
|
|
||||||
else
|
|
||||||
logOpSize = 2; // 32 bit operand size
|
|
||||||
}
|
|
||||||
else // 16 bit default operand size
|
|
||||||
{
|
|
||||||
if(emi.legacy.op)
|
|
||||||
logOpSize = 2; // 32 bit operand size
|
|
||||||
else
|
|
||||||
logOpSize = 1; // 16 bit operand size
|
|
||||||
}
|
|
||||||
|
|
||||||
//Set the actual op size
|
//Set the actual op size
|
||||||
emi.opSize = 1 << logOpSize;
|
emi.opSize = 1 << logOpSize;
|
||||||
|
@ -251,41 +232,18 @@ namespace X86ISA
|
||||||
//Figure out the effective address size. This can be overriden to
|
//Figure out the effective address size. This can be overriden to
|
||||||
//a fixed value at the decoder level.
|
//a fixed value at the decoder level.
|
||||||
int logAddrSize;
|
int logAddrSize;
|
||||||
if(emi.mode.submode == SixtyFourBitMode)
|
|
||||||
{
|
|
||||||
if(emi.legacy.addr)
|
if(emi.legacy.addr)
|
||||||
logAddrSize = 2; // 32 bit address size
|
logAddrSize = m5Reg.altAddr;
|
||||||
else
|
else
|
||||||
logAddrSize = 3; // 64 bit address size
|
logAddrSize = m5Reg.defAddr;
|
||||||
}
|
|
||||||
else if(csAttr.defaultSize)
|
|
||||||
{
|
|
||||||
if(emi.legacy.addr)
|
|
||||||
logAddrSize = 1; // 16 bit address size
|
|
||||||
else
|
|
||||||
logAddrSize = 2; // 32 bit address size
|
|
||||||
}
|
|
||||||
else // 16 bit default operand size
|
|
||||||
{
|
|
||||||
if(emi.legacy.addr)
|
|
||||||
logAddrSize = 2; // 32 bit address size
|
|
||||||
else
|
|
||||||
logAddrSize = 1; // 16 bit address size
|
|
||||||
}
|
|
||||||
|
|
||||||
SegAttr ssAttr = tc->readMiscRegNoEffect(MISCREG_SS_ATTR);
|
|
||||||
//Figure out the effective stack width. This can be overriden to
|
|
||||||
//a fixed value at the decoder level.
|
|
||||||
if(emi.mode.submode == SixtyFourBitMode)
|
|
||||||
emi.stackSize = 8; // 64 bit stack width
|
|
||||||
else if(ssAttr.defaultSize)
|
|
||||||
emi.stackSize = 4; // 32 bit stack width
|
|
||||||
else
|
|
||||||
emi.stackSize = 2; // 16 bit stack width
|
|
||||||
|
|
||||||
//Set the actual address size
|
//Set the actual address size
|
||||||
emi.addrSize = 1 << logAddrSize;
|
emi.addrSize = 1 << logAddrSize;
|
||||||
|
|
||||||
|
//Figure out the effective stack width. This can be overriden to
|
||||||
|
//a fixed value at the decoder level.
|
||||||
|
emi.stackSize = 1 << m5Reg.stack;
|
||||||
|
|
||||||
//Figure out how big of an immediate we'll retreive based
|
//Figure out how big of an immediate we'll retreive based
|
||||||
//on the opcode.
|
//on the opcode.
|
||||||
int immType = ImmediateType[emi.opcode.num - 1][nextByte];
|
int immType = ImmediateType[emi.opcode.num - 1][nextByte];
|
||||||
|
@ -318,9 +276,7 @@ namespace X86ISA
|
||||||
ModRM modRM;
|
ModRM modRM;
|
||||||
modRM = nextByte;
|
modRM = nextByte;
|
||||||
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
|
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
|
||||||
SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
|
if (m5Reg.defOp == 1) {
|
||||||
if (emi.mode.submode != SixtyFourBitMode &&
|
|
||||||
!csAttr.defaultSize) {
|
|
||||||
//figure out 16 bit displacement size
|
//figure out 16 bit displacement size
|
||||||
if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
|
if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
|
||||||
displacementSize = 2;
|
displacementSize = 2;
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "arch/x86/types.hh"
|
#include "arch/x86/types.hh"
|
||||||
|
#include "arch/x86/miscregs.hh"
|
||||||
#include "base/bitfield.hh"
|
#include "base/bitfield.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
@ -91,10 +92,11 @@ namespace X86ISA
|
||||||
int offset;
|
int offset;
|
||||||
//The extended machine instruction being generated
|
//The extended machine instruction being generated
|
||||||
ExtMachInst emi;
|
ExtMachInst emi;
|
||||||
|
HandyM5Reg m5Reg;
|
||||||
|
|
||||||
inline uint8_t getNextByte()
|
inline uint8_t getNextByte()
|
||||||
{
|
{
|
||||||
return (fetchChunk >> (offset * 8)) & 0xff;
|
return ((uint8_t *)&fetchChunk)[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
void getImmediate(int &collected, uint64_t ¤t, int size)
|
void getImmediate(int &collected, uint64_t ¤t, int size)
|
||||||
|
@ -182,6 +184,7 @@ namespace X86ISA
|
||||||
{
|
{
|
||||||
emi.mode.mode = LongMode;
|
emi.mode.mode = LongMode;
|
||||||
emi.mode.submode = SixtyFourBitMode;
|
emi.mode.submode = SixtyFourBitMode;
|
||||||
|
m5Reg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
|
|
|
@ -232,6 +232,15 @@ X86_64LiveProcess::startup()
|
||||||
|
|
||||||
tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr);
|
tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr);
|
||||||
|
|
||||||
|
Efer efer = 0;
|
||||||
|
efer.sce = 1; // Enable system call extensions.
|
||||||
|
efer.lme = 1; // Enable long mode.
|
||||||
|
efer.lma = 1; // Activate long mode.
|
||||||
|
efer.nxe = 1; // Enable nx support.
|
||||||
|
efer.svme = 0; // Disable svm support for now. It isn't implemented.
|
||||||
|
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
|
||||||
|
tc->setMiscReg(MISCREG_EFER, efer);
|
||||||
|
|
||||||
//Set up the registers that describe the operating mode.
|
//Set up the registers that describe the operating mode.
|
||||||
CR0 cr0 = 0;
|
CR0 cr0 = 0;
|
||||||
cr0.pg = 1; // Turn on paging.
|
cr0.pg = 1; // Turn on paging.
|
||||||
|
@ -248,15 +257,6 @@ X86_64LiveProcess::startup()
|
||||||
// setting it to one.
|
// setting it to one.
|
||||||
cr0.pe = 1; // We're definitely in protected mode.
|
cr0.pe = 1; // We're definitely in protected mode.
|
||||||
tc->setMiscReg(MISCREG_CR0, cr0);
|
tc->setMiscReg(MISCREG_CR0, cr0);
|
||||||
|
|
||||||
Efer efer = 0;
|
|
||||||
efer.sce = 1; // Enable system call extensions.
|
|
||||||
efer.lme = 1; // Enable long mode.
|
|
||||||
efer.lma = 1; // Activate long mode.
|
|
||||||
efer.nxe = 1; // Enable nx support.
|
|
||||||
efer.svme = 0; // Disable svm support for now. It isn't implemented.
|
|
||||||
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
|
|
||||||
tc->setMiscReg(MISCREG_EFER, efer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,6 +340,15 @@ I386LiveProcess::startup()
|
||||||
// Set the LDT selector to 0 to deactivate it.
|
// Set the LDT selector to 0 to deactivate it.
|
||||||
tc->setMiscRegNoEffect(MISCREG_TSL, 0);
|
tc->setMiscRegNoEffect(MISCREG_TSL, 0);
|
||||||
|
|
||||||
|
Efer efer = 0;
|
||||||
|
efer.sce = 1; // Enable system call extensions.
|
||||||
|
efer.lme = 1; // Enable long mode.
|
||||||
|
efer.lma = 0; // Deactivate long mode.
|
||||||
|
efer.nxe = 1; // Enable nx support.
|
||||||
|
efer.svme = 0; // Disable svm support for now. It isn't implemented.
|
||||||
|
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
|
||||||
|
tc->setMiscReg(MISCREG_EFER, efer);
|
||||||
|
|
||||||
//Set up the registers that describe the operating mode.
|
//Set up the registers that describe the operating mode.
|
||||||
CR0 cr0 = 0;
|
CR0 cr0 = 0;
|
||||||
cr0.pg = 1; // Turn on paging.
|
cr0.pg = 1; // Turn on paging.
|
||||||
|
@ -356,15 +365,6 @@ I386LiveProcess::startup()
|
||||||
// setting it to one.
|
// setting it to one.
|
||||||
cr0.pe = 1; // We're definitely in protected mode.
|
cr0.pe = 1; // We're definitely in protected mode.
|
||||||
tc->setMiscReg(MISCREG_CR0, cr0);
|
tc->setMiscReg(MISCREG_CR0, cr0);
|
||||||
|
|
||||||
Efer efer = 0;
|
|
||||||
efer.sce = 1; // Enable system call extensions.
|
|
||||||
efer.lme = 1; // Enable long mode.
|
|
||||||
efer.lma = 0; // Deactivate long mode.
|
|
||||||
efer.nxe = 1; // Enable nx support.
|
|
||||||
efer.svme = 0; // Disable svm support for now. It isn't implemented.
|
|
||||||
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
|
|
||||||
tc->setMiscReg(MISCREG_EFER, efer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,21 +186,10 @@ TLB::demapPage(Addr va, uint64_t asn)
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
TLB::translateInt(RequestPtr req, ThreadContext *tc)
|
||||||
Mode mode, bool &delayedResponse, bool timing)
|
|
||||||
{
|
{
|
||||||
delayedResponse = false;
|
|
||||||
Addr vaddr = req->getVaddr();
|
|
||||||
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
|
|
||||||
uint32_t flags = req->getFlags();
|
|
||||||
bool storeCheck = flags & (StoreCheck << FlagShift);
|
|
||||||
|
|
||||||
int seg = flags & SegmentFlagMask;
|
|
||||||
|
|
||||||
// If this is true, we're dealing with a request to read an internal
|
|
||||||
// value.
|
|
||||||
if (seg == SEGMENT_REG_MS) {
|
|
||||||
DPRINTF(TLB, "Addresses references internal memory.\n");
|
DPRINTF(TLB, "Addresses references internal memory.\n");
|
||||||
|
Addr vaddr = req->getVaddr();
|
||||||
Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
|
Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
|
||||||
if (prefix == IntAddrPrefixCPUID) {
|
if (prefix == IntAddrPrefixCPUID) {
|
||||||
panic("CPUID memory space not yet implemented!\n");
|
panic("CPUID memory space not yet implemented!\n");
|
||||||
|
@ -555,22 +544,35 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get cr0. This will tell us how to do translation. We'll assume it was
|
Fault
|
||||||
// verified to be correct and consistent when set.
|
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
||||||
CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
|
Mode mode, bool &delayedResponse, bool timing)
|
||||||
|
{
|
||||||
|
uint32_t flags = req->getFlags();
|
||||||
|
int seg = flags & SegmentFlagMask;
|
||||||
|
bool storeCheck = flags & (StoreCheck << FlagShift);
|
||||||
|
|
||||||
|
// If this is true, we're dealing with a request to a non-memory address
|
||||||
|
// space.
|
||||||
|
if (seg == SEGMENT_REG_MS) {
|
||||||
|
return translateInt(req, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
delayedResponse = false;
|
||||||
|
Addr vaddr = req->getVaddr();
|
||||||
|
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
|
||||||
|
|
||||||
|
HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
||||||
|
|
||||||
// If protected mode has been enabled...
|
// If protected mode has been enabled...
|
||||||
if (cr0.pe) {
|
if (m5Reg.prot) {
|
||||||
DPRINTF(TLB, "In protected mode.\n");
|
DPRINTF(TLB, "In protected mode.\n");
|
||||||
Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
|
|
||||||
SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
|
|
||||||
// If we're not in 64-bit mode, do protection/limit checks
|
// If we're not in 64-bit mode, do protection/limit checks
|
||||||
if (!efer.lma || !csAttr.longMode) {
|
if (m5Reg.mode != LongMode) {
|
||||||
DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
|
DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
|
||||||
// Check for a NULL segment selector.
|
// Check for a NULL segment selector.
|
||||||
if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR ||
|
if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR ||
|
||||||
seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS ||
|
seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS)
|
||||||
seg == SEGMENT_REG_MS)
|
|
||||||
&& !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
|
&& !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
|
||||||
return new GeneralProtection(0);
|
return new GeneralProtection(0);
|
||||||
bool expandDown = false;
|
bool expandDown = false;
|
||||||
|
@ -589,6 +591,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
||||||
// address size is 64 bits, overridable to 32.
|
// address size is 64 bits, overridable to 32.
|
||||||
int size = 32;
|
int size = 32;
|
||||||
bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift));
|
bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift));
|
||||||
|
SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
|
||||||
if ((csAttr.defaultSize && sizeOverride) ||
|
if ((csAttr.defaultSize && sizeOverride) ||
|
||||||
(!csAttr.defaultSize && !sizeOverride))
|
(!csAttr.defaultSize && !sizeOverride))
|
||||||
size = 16;
|
size = 16;
|
||||||
|
@ -605,7 +608,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If paging is enabled, do the translation.
|
// If paging is enabled, do the translation.
|
||||||
if (cr0.pg) {
|
if (m5Reg.paging) {
|
||||||
DPRINTF(TLB, "Paging enabled.\n");
|
DPRINTF(TLB, "Paging enabled.\n");
|
||||||
// The vaddr already has the segment base applied.
|
// The vaddr already has the segment base applied.
|
||||||
TlbEntry *entry = lookup(vaddr);
|
TlbEntry *entry = lookup(vaddr);
|
||||||
|
@ -643,7 +646,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// Do paging protection checks.
|
// Do paging protection checks.
|
||||||
bool inUser = (csAttr.dpl == 3 &&
|
bool inUser = (m5Reg.cpl == 3 &&
|
||||||
!(flags & (CPL0FlagBit << FlagShift)));
|
!(flags & (CPL0FlagBit << FlagShift)));
|
||||||
if ((inUser && !entry->user) ||
|
if ((inUser && !entry->user) ||
|
||||||
(mode == Write && !entry->writable)) {
|
(mode == Write && !entry->writable)) {
|
||||||
|
|
|
@ -124,6 +124,8 @@ namespace X86ISA
|
||||||
EntryList freeList;
|
EntryList freeList;
|
||||||
EntryList entryList;
|
EntryList entryList;
|
||||||
|
|
||||||
|
Fault translateInt(RequestPtr req, ThreadContext *tc);
|
||||||
|
|
||||||
Fault translate(RequestPtr req, ThreadContext *tc,
|
Fault translate(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, Mode mode,
|
Translation *translation, Mode mode,
|
||||||
bool &delayedResponse, bool timing);
|
bool &delayedResponse, bool timing);
|
||||||
|
|
|
@ -41,7 +41,7 @@ Source('debug.cc')
|
||||||
Source('eventq.cc')
|
Source('eventq.cc')
|
||||||
Source('faults.cc')
|
Source('faults.cc')
|
||||||
Source('init.cc')
|
Source('init.cc')
|
||||||
BinSource('main.cc')
|
Source('main.cc', bin_only=True)
|
||||||
Source('pseudo_inst.cc')
|
Source('pseudo_inst.cc')
|
||||||
Source('root.cc')
|
Source('root.cc')
|
||||||
Source('serialize.cc')
|
Source('serialize.cc')
|
||||||
|
|
Loading…
Reference in a new issue