This commit is contained in:
Derek Hower 2010-01-19 15:48:12 -06:00
commit 279f179bab
682 changed files with 26213 additions and 20254 deletions

View file

@ -7,3 +7,4 @@ cscope.out
*.pyc
*~
.*.swp
m5out

View file

@ -96,6 +96,7 @@ For more details, see:
"""
raise
# Global Python includes
import os
import re
import subprocess
@ -106,55 +107,18 @@ 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
def read_command(cmd, **kwargs):
"""run the command cmd, read the results and return them
this is sorta like `cmd` in shell"""
from subprocess import Popen, PIPE, STDOUT
if isinstance(cmd, str):
cmd = cmd.split()
no_exception = 'exception' in kwargs
exception = kwargs.pop('exception', None)
extra_python_paths = [
Dir('src/python').srcnode().abspath, # M5 includes
Dir('ext/ply').srcnode().abspath, # ply is used by several files
]
kwargs.setdefault('shell', False)
kwargs.setdefault('stdout', PIPE)
kwargs.setdefault('stderr', STDOUT)
kwargs.setdefault('close_fds', True)
try:
subp = Popen(cmd, **kwargs)
except Exception, e:
if no_exception:
return exception
raise
sys.path[1:1] = extra_python_paths
return subp.communicate()[0]
# helper function: compare arrays or strings of version numbers.
# E.g., compare_version((1,3,25), (1,4,1)')
# returns -1, 0, 1 if v1 is <, ==, > v2
def compare_versions(v1, v2):
def make_version_list(v):
if isinstance(v, (list,tuple)):
return v
elif isinstance(v, str):
return map(lambda x: int(re.match('\d+', x).group()), v.split('.'))
else:
raise TypeError
v1 = make_version_list(v1)
v2 = make_version_list(v2)
# Compare corresponding elements of lists
for n1,n2 in zip(v1, v2):
if n1 < n2: return -1
if n1 > n2: return 1
# all corresponding values are equal... see if one has extra values
if len(v1) < len(v2): return -1
if len(v1) > len(v2): return 1
return 0
from m5.util import compareVersions, readCommand
########################################################################
#
@ -162,7 +126,7 @@ def compare_versions(v1, v2):
#
########################################################################
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
'RANLIB' ])
'PYTHONPATH', 'RANLIB' ])
use_env = {}
for key,val in os.environ.iteritems():
@ -173,6 +137,10 @@ main = Environment(ENV=use_env)
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.
@ -217,7 +185,7 @@ if hgdir.exists():
# 1) Grab repository revision if we know it.
cmd = "hg id -n -i -t -b"
try:
hg_info = read_command(cmd, cwd=main.root.abspath).strip()
hg_info = readCommand(cmd, cwd=main.root.abspath).strip()
except OSError:
print mercurial_bin_not_found
@ -378,11 +346,8 @@ Export('extras_dir_list')
# the ext directory should be on the #includes path
main.Append(CPPPATH=[Dir('ext')])
# M5_PLY is used by isa_parser.py to find the PLY package.
main.Append(ENV = { 'M5_PLY' : Dir('ext/ply').abspath })
CXX_version = read_command([main['CXX'],'--version'], exception=False)
CXX_V = read_command([main['CXX'],'-V'], exception=False)
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
@ -426,7 +391,7 @@ if main['BATCH']:
if sys.platform == 'cygwin':
# cygwin has some header file issues...
main.Append(CCFLAGS=Split("-Wno-uninitialized"))
main.Append(CCFLAGS="-Wno-uninitialized")
# Check for SWIG
if not main.has_key('SWIG'):
@ -435,7 +400,7 @@ if not main.has_key('SWIG'):
Exit(1)
# Check for appropriate SWIG version
swig_version = read_command(('swig', '-version'), exception='').split()
swig_version = readCommand(('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':
@ -443,7 +408,7 @@ if len(swig_version) < 3 or \
Exit(1)
min_swig_version = '1.3.28'
if compare_versions(swig_version[2], min_swig_version) < 0:
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)
@ -514,8 +479,8 @@ conf.CheckLeading()
try:
import platform
uname = platform.uname()
if uname[0] == 'Darwin' and compare_versions(uname[2], '9.0.0') >= 0:
if int(read_command('sysctl -n hw.cpu64bit_capable')[0]):
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')
@ -615,9 +580,9 @@ have_mysql = bool(mysql_config)
# Check MySQL version.
if have_mysql:
mysql_version = read_command(mysql_config + ' --version')
mysql_version = readCommand(mysql_config + ' --version')
min_mysql_version = '4.1'
if compare_versions(mysql_version, min_mysql_version) < 0:
if compareVersions(mysql_version, min_mysql_version) < 0:
print 'Warning: MySQL', min_mysql_version, 'or newer required.'
print ' Version', mysql_version, 'detected.'
have_mysql = False
@ -777,17 +742,10 @@ def make_switching_dir(dname, switch_headers, env):
# list of ISAs from env['ALL_ISA_LIST'].
def gen_switch_hdr(target, source, env):
fname = str(target[0])
bname = basename(fname)
f = open(fname, 'w')
f.write('#include "arch/isa_specific.hh"\n')
cond = '#if'
for isa in all_isa_list:
f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n'
% (cond, isa.upper(), dname, isa, bname))
cond = '#elif'
f.write('#else\n#error "THE_ISA not set"\n#endif\n')
isa = env['TARGET_ISA'].lower()
print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
f.close()
return 0
# String to print when generating header
def gen_switch_hdr_string(target, source, env):

3
build_opts/ARM_FS Normal file
View file

@ -0,0 +1,3 @@
TARGET_ISA = 'arm'
CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU'
FULL_SYSTEM = 1

3
build_opts/POWER_SE Normal file
View file

@ -0,0 +1,3 @@
TARGET_ISA = 'power'
FULL_SYSTEM = 0
CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU'

View file

@ -26,7 +26,6 @@
#
# Authors: Lisa Hsu
import m5
from m5.objects import *
class L1Cache(BaseCache):

View file

@ -26,8 +26,6 @@
#
# Authors: Kevin Lim
import m5
from m5 import makeList
from m5.objects import *
from Benchmarks import *
@ -81,6 +79,50 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
return self
def makeLinuxAlphaRubySystem(mem_mode, rubymem, 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)
self = LinuxAlphaSystem(physmem = rubymem)
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 = Bus(bus_id=0)
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.port
self.tsunami.ethernet.pio = self.piobus.port
# connect the dma ports directly to ruby dma ports
self.tsunami.ide.dma = self.physmem.dma_port
self.tsunami.ethernet.dma = self.physmem.dma_port
# connect the pio bus to rubymem
self.physmem.pio_port = self.piobus.port
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):
class CowMmDisk(MmDisk):
image = CowDiskImage(child=RawDiskImage(read_only=True),

View file

@ -38,6 +38,7 @@ parser.add_option("--fastmem", action="store_true")
# Run duration options
parser.add_option("-m", "--maxtick", type="int")
parser.add_option("--maxtime", type="float")
parser.add_option("--maxinsts", type="int")
parser.add_option("--prog_intvl", type="int")
@ -52,6 +53,9 @@ 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 <N>")
parser.add_option("--checkpoint-at-end", action="store_true",
help="take a checkpoint at end of run")
# CPU Switching - default switch model goes from a checkpoint
# to a timing simple CPU with caches to warm up, then to detailed CPU for
@ -61,6 +65,7 @@ parser.add_option("-s", "--standard-switch", action="store_true",
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("--profile", help="CPU profile interval")
# Fastforwarding and simpoint related materials
parser.add_option("-W", "--warmup-insts", action="store", type="int",

View file

@ -28,9 +28,13 @@
from os import getcwd
from os.path import join as joinpath
import m5
from m5.defines import buildEnv
from m5.objects import *
m5.AddToPath('../common')
from m5.util import *
addToPath('../common')
def setCPUClass(options):
@ -82,10 +86,10 @@ def run(options, root, testsys, cpu_class):
cptdir = getcwd()
if options.fast_forward and options.checkpoint_restore != None:
m5.fatal("Error: Can't specify both --fast-forward and --checkpoint-restore")
fatal("Can't specify both --fast-forward and --checkpoint-restore")
if options.standard_switch and not options.caches:
m5.fatal("Error: Must specify --caches when using --standard-switch")
fatal("Must specify --caches when using --standard-switch")
np = options.num_cpus
max_checkpoints = options.max_checkpoints
@ -95,6 +99,10 @@ def run(options, root, testsys, cpu_class):
for i in xrange(np):
testsys.cpu[i].progress_interval = options.prog_intvl
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)]
@ -103,7 +111,7 @@ def run(options, root, testsys, cpu_class):
if options.fast_forward:
testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
switch_cpus[i].system = testsys
if not m5.build_env['FULL_SYSTEM']:
if not buildEnv['FULL_SYSTEM']:
switch_cpus[i].workload = testsys.cpu[i].workload
switch_cpus[i].clock = testsys.cpu[0].clock
# simulation period
@ -122,7 +130,7 @@ def run(options, root, testsys, cpu_class):
for i in xrange(np):
switch_cpus[i].system = testsys
switch_cpus_1[i].system = testsys
if not m5.build_env['FULL_SYSTEM']:
if not buildEnv['FULL_SYSTEM']:
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
@ -137,7 +145,7 @@ def run(options, root, testsys, cpu_class):
# Fast forward to a simpoint (warning: time consuming)
elif options.simpoint:
if testsys.cpu[i].workload[0].simpoint == 0:
m5.fatal('simpoint not found')
fatal('simpoint not found')
testsys.cpu[i].max_insts_any_thread = \
testsys.cpu[i].workload[0].simpoint
# No distance specified, just switch
@ -170,7 +178,7 @@ def run(options, root, testsys, cpu_class):
if options.simpoint:
for i in xrange(np):
if testsys.cpu[i].workload[0].simpoint == 0:
m5.fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
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
@ -190,14 +198,13 @@ def run(options, root, testsys, cpu_class):
import re
if not isdir(cptdir):
m5.fatal("checkpoint dir %s does not exist!", cptdir)
fatal("checkpoint dir %s does not exist!", cptdir)
if options.at_instruction:
checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
(options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir):
m5.fatal("Unable to find checkpoint directory %s",
checkpoint_dir)
fatal("Unable to find checkpoint directory %s", checkpoint_dir)
print "Restoring checkpoint ..."
m5.restoreCheckpoint(root, checkpoint_dir)
@ -205,7 +212,7 @@ def run(options, root, testsys, cpu_class):
elif options.simpoint:
# assume workload 0 has the simpoint
if testsys.cpu[0].workload[0].simpoint == 0:
m5.fatal('Unable to find simpoint')
fatal('Unable to find simpoint')
options.checkpoint_restore += \
int(testsys.cpu[0].workload[0].simpoint)
@ -213,8 +220,8 @@ def run(options, root, testsys, cpu_class):
checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
(options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir):
m5.fatal("Unable to find checkpoint directory %s.%s",
options.bench, options.checkpoint_restore)
fatal("Unable to find checkpoint directory %s.%s",
options.bench, options.checkpoint_restore)
print "Restoring checkpoint ..."
m5.restoreCheckpoint(root,checkpoint_dir)
@ -233,7 +240,7 @@ def run(options, root, testsys, cpu_class):
cpt_num = options.checkpoint_restore
if cpt_num > len(cpts):
m5.fatal('Checkpoint %d not found', cpt_num)
fatal('Checkpoint %d not found', cpt_num)
## Adjust max tick based on our starting tick
maxtick = maxtick - int(cpts[cpt_num - 1])
@ -367,3 +374,6 @@ def run(options, root, testsys, cpu_class):
exit_cause = exit_event.getCause()
print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause)
if options.checkpoint_at_end:
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))

View file

@ -26,15 +26,20 @@
#
# Authors: Ali Saidi
import optparse, os, sys
import optparse
import os
import sys
import m5
if not m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires full-system mode (*_FS).")
from m5.defines import buildEnv
from m5.objects import *
m5.AddToPath('../common')
from m5.util import addToPath, fatal
if not buildEnv['FULL_SYSTEM']:
fatal("This script requires full-system mode (*_FS).")
addToPath('../common')
from FSConfig import *
from SysPaths import *
from Benchmarks import *
@ -98,16 +103,16 @@ else:
np = options.num_cpus
if m5.build_env['TARGET_ISA'] == "alpha":
if buildEnv['TARGET_ISA'] == "alpha":
test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0])
elif m5.build_env['TARGET_ISA'] == "mips":
elif buildEnv['TARGET_ISA'] == "mips":
test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0])
elif m5.build_env['TARGET_ISA'] == "sparc":
elif buildEnv['TARGET_ISA'] == "sparc":
test_sys = makeSparcSystem(test_mem_mode, bm[0])
elif m5.build_env['TARGET_ISA'] == "x86":
elif buildEnv['TARGET_ISA'] == "x86":
test_sys = makeLinuxX86System(test_mem_mode, np, bm[0])
else:
m5.fatal("incapable of building non-alpha or non-sparc full system!")
fatal("incapable of building non-alpha or non-sparc full system!")
if options.kernel is not None:
test_sys.kernel = binary(options.kernel)
@ -123,7 +128,7 @@ if options.l2cache:
test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
if options.caches:
if options.caches or options.l2cache:
test_sys.bridge.filter_ranges_a=[AddrRange(0, Addr.max)]
test_sys.bridge.filter_ranges_b=[AddrRange(0, size='8GB')]
test_sys.iocache = IOCache(addr_range=AddrRange(0, size='8GB'))
@ -142,17 +147,17 @@ for i in xrange(np):
if options.fastmem:
test_sys.cpu[i].physmem_port = test_sys.physmem.port
if m5.build_env['TARGET_ISA'] == 'mips':
if buildEnv['TARGET_ISA'] == 'mips':
setMipsOptions(TestCPUClass)
if len(bm) == 2:
if m5.build_env['TARGET_ISA'] == 'alpha':
if buildEnv['TARGET_ISA'] == 'alpha':
drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
elif m5.build_env['TARGET_ISA'] == 'mips':
elif buildEnv['TARGET_ISA'] == 'mips':
drive_sys = makeLinuxMipsSystem(drive_mem_mode, bm[1])
elif m5.build_env['TARGET_ISA'] == 'sparc':
elif buildEnv['TARGET_ISA'] == 'sparc':
drive_sys = makeSparcSystem(drive_mem_mode, bm[1])
elif m5.build.env['TARGET_ISA'] == 'x86':
elif buildEnv['TARGET_ISA'] == 'x86':
drive_sys = makeX86System(drive_mem_mode, np, bm[1])
drive_sys.cpu = DriveCPUClass(cpu_id=0)
drive_sys.cpu.connectMemPorts(drive_sys.membus)

View file

@ -0,0 +1,122 @@
# 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('../../tests/configs/')
import ruby_config
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")
parser.add_option("-t", "--testers", type="int", metavar="N", default=1,
help="number of testers/cores")
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
if options.testers > block_size:
print "Error: Number of testers %d limited to %d because of false sharing" \
% (options.testers, block_size)
sys.exit(1)
cpus = [ MemTest(atomic=options.atomic, max_loads=options.maxloads, \
percent_functional=options.functional, \
percent_uncacheable=options.uncacheable, \
progress_interval=options.progress) \
for i in xrange(options.testers) ]
# create the desired simulated system
# ruby memory must be at least 16 MB to work with the mem tester
ruby_memory = ruby_config.generate("MI_example-homogeneous.rb",
cores = options.testers,
memory_size = 16,
ports_per_cpu = 1)
system = System(cpu = cpus, funcmem = PhysicalMemory(),
physmem = ruby_memory)
for cpu in cpus:
cpu.test = system.physmem.port
cpu.functional = system.funcmem.port
# -----------------------
# run simulation
# -----------------------
root = Root( system = system )
if options.atomic:
root.system.mem_mode = 'atomic'
else:
root.system.mem_mode = 'timing'
# Not much point in this being higher than the L1 latency
m5.ticks.setGlobalFrequency('1ns')
# instantiate configuration
m5.instantiate(root)
# simulate until program terminates
exit_event = m5.simulate(options.maxtick)
print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()

View file

@ -26,10 +26,11 @@
#
# Authors: Ron Dreslinski
import optparse
import sys
import m5
from m5.objects import *
import os, optparse, sys
m5.AddToPath('../common')
parser = optparse.OptionParser()

201
configs/example/ruby_fs.py Normal file
View file

@ -0,0 +1,201 @@
# 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
#
# Full system configuraiton for ruby
#
import os
import optparse
import sys
from os.path import join as joinpath
import m5
from m5.defines import buildEnv
from m5.objects import *
from m5.util import addToPath, panic
if not buildEnv['FULL_SYSTEM']:
panic("This script requires full-system mode (*_FS).")
addToPath('../../tests/configs/')
addToPath('../common')
import ruby_config
from FSConfig import *
from SysPaths import *
from Benchmarks import *
import Simulation
from Caches import *
# 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()
# Benchmark options
parser.add_option("-b", "--benchmark", action="store", type="string",
dest="benchmark",
help="Specify the benchmark to run. Available benchmarks: %s"\
% DefinedBenchmarks)
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.")
# ruby options
parser.add_option("--ruby-debug", action="store_true")
parser.add_option("--ruby-debug-file", default="", help="Ruby debug out file (stdout if blank)")
parser.add_option("--protocol", default="", help="Ruby protocol compiled into binary")
# ruby host memory experimentation
parser.add_option("--cache_size", type="int")
parser.add_option("--cache_assoc", type="int")
parser.add_option("--map_levels", type="int")
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)
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()]
#
# currently ruby fs only works in simple timing mode because ruby does not
# support atomic accesses by devices. Also ruby_fs currently assumes
# that is running a checkpoints that were created by ALPHA_FS under atomic
# mode. Since switch cpus are not defined in these checkpoints, we don't
# fast forward with the atomic cpu and instead set the FutureClass to None.
# Therefore the cpus resolve to the correct names and unserialize correctly.
#
assert(options.timing)
class CPUClass(TimingSimpleCPU): pass
test_mem_mode = 'timing'
FutureClass = None
CPUClass.clock = '1GHz'
#
# Since we are running in timing mode, set the number of M5 ticks to ruby ticks
# to the cpu clock frequency
#
M5_to_ruby_tick = '1000t'
np = options.num_cpus
# check for max instruction count
if options.max_inst:
max_inst = options.max_inst
else:
max_inst = 0
# set cache size
if options.cache_size:
cache_size = options.cache_size
else:
cache_size = 32768 # 32 kB is default
# set cache assoc
if options.cache_assoc:
cache_assoc = options.cache_assoc
else:
cache_assoc = 8 # 8 is default
# set map levels
if options.map_levels:
map_levels = options.map_levels
else:
map_levels = 4 # 4 levels is the default
if options.protocol == "MOESI_hammer":
ruby_config_file = "MOESI_hammer-homogeneous.rb"
elif options.protocol == "MOESI_CMP_token":
ruby_config_file = "TwoLevel_SplitL1UnifiedL2.rb"
elif options.protocol == "MI_example":
ruby_config_file = "MI_example-homogeneous.rb"
else:
print "Error: unsupported ruby protocol"
sys.exit(1)
#
# Currently, since ruby configuraiton is separate from m5, we need to manually
# tell ruby that two dma ports are created by makeLinuxAlphaRubySystem().
# Eventually, this will be fix with a unified configuration system.
#
rubymem = ruby_config.generate(ruby_config_file,
np,
np,
128,
False,
cache_size,
cache_assoc,
map_levels,
2,
M5_to_ruby_tick)
if options.ruby_debug == True:
rubymem.debug = True
rubymem.debug_file = options.ruby_debug_file
system = makeLinuxAlphaRubySystem(test_mem_mode, rubymem, bm[0])
system.cpu = [CPUClass(cpu_id=i) for i in xrange(np)]
if options.l2cache:
print "Error: -l2cache incompatible with ruby, must configure it ruby-style"
sys.exit(1)
if options.caches:
print "Error: -caches incompatible with ruby, must configure it ruby-style"
sys.exit(1)
for i in xrange(np):
system.cpu[i].connectMemPorts(system.physmem)
if options.fastmem:
system.cpu[i].physmem_port = system.physmem.port
root = Root(system = system)
Simulation.run(options, root, system, FutureClass)

View file

@ -30,17 +30,22 @@
#
# "m5 test.py"
import m5
if m5.build_env['FULL_SYSTEM']:
m5.panic("This script requires syscall emulation mode (*_SE).")
from m5.objects import *
import os, optparse, sys
import os
import optparse
import sys
from os.path import join as joinpath
m5.AddToPath('../common')
import m5
from m5.defines import buildEnv
from m5.objects import *
from m5.util import addToPath, panic
if buildEnv['FULL_SYSTEM']:
panic("This script requires syscall emulation mode (*_SE).")
addToPath('../common')
import Simulation
#from Caches import *
from cpu2000 import *
# Get paths we might need. It's expected this file is in m5/configs/example.
@ -72,7 +77,7 @@ if args:
if options.bench:
try:
if m5.build_env['TARGET_ISA'] != 'alpha':
if buildEnv['TARGET_ISA'] != 'alpha':
print >>sys.stderr, "Simpoints code only works for Alpha ISA at this time"
sys.exit(1)
exec("workload = %s('alpha', 'tru64', 'ref')" % options.bench)
@ -133,7 +138,6 @@ rubymem = RubyMemory(
range = AddrRange("512MB"),
clock = "1GHz",
num_cpus = np,
libruby_file = "src/mem/ruby/amd64-linux/generated/MOESI_CMP_directory/bin/libruby.so",
config_file = "ruby.config",
stats_file = "m5out/ruby.stats"
)

View file

@ -30,15 +30,21 @@
#
# "m5 test.py"
import m5
if m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires syscall emulation mode (*_SE).")
from m5.objects import *
import os, optparse, sys
import os
import optparse
import sys
from os.path import join as joinpath
m5.AddToPath('../common')
import m5
from m5.defines import buildEnv
from m5.objects import *
from m5.util import addToPath, fatal
if buildEnv['FULL_SYSTEM']:
fatal("This script requires syscall emulation mode (*_SE).")
addToPath('../common')
import Simulation
from Caches import *
from cpu2000 import *
@ -70,7 +76,7 @@ if args:
if options.bench:
try:
if m5.build_env['TARGET_ISA'] != 'alpha':
if buildEnv['TARGET_ISA'] != 'alpha':
print >>sys.stderr, "Simpoints code only works for Alpha ISA at this time"
sys.exit(1)
exec("workload = %s('alpha', 'tru64', 'ref')" % options.bench)
@ -94,8 +100,9 @@ if options.errout != "":
# By default, set workload to path of user-specified binary
workloads = options.cmd
numThreads = 1
if options.detailed:
if options.detailed or options.inorder:
#check for SMT workload
workloads = options.cmd.split(';')
if len(workloads) > 1:
@ -124,11 +131,12 @@ if options.detailed:
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 = len(workloads)
CPUClass.numThreads = numThreads;
np = options.num_cpus

View file

@ -30,10 +30,14 @@
#
# "m5 test.py"
import os
import optparse
import sys
import m5
from m5.objects import *
import os, optparse, sys
m5.AddToPath('../common')
m5.util.addToPath('../common')
# --------------------
# Define Command Line Options
@ -266,10 +270,11 @@ elif options.benchmark == 'WaterNSquared':
elif options.benchmark == 'WaterSpatial':
root.workload = Water_spatial()
else:
panic("The --benchmark environment variable was set to something" \
+" improper.\nUse Cholesky, FFT, LUContig, LUNoncontig, Radix" \
+", Barnes, FMM, OceanContig,\nOceanNoncontig, Raytrace," \
+" WaterNSquared, or WaterSpatial\n")
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

View file

@ -29,10 +29,14 @@
# Splash2 Run Script
#
import os
import optparse
import sys
import m5
from m5.objects import *
import os, optparse, sys
m5.AddToPath('../common')
m5.util.addToPath('../common')
# --------------------
# Define Command Line Options

View file

@ -49,7 +49,7 @@ Import('*')
# Children need to see the environment
Export('env')
build_env = dict([(opt, env[opt]) for opt in export_vars])
build_env = [(opt, env[opt]) for opt in export_vars]
########################################################################
# Code for adding source files of various types
@ -132,15 +132,15 @@ class PySource(SourceFile):
modpath = '.'.join(modpath)
arcpath = path + [ self.basename ]
debugname = self.snode.abspath
if not exists(debugname):
debugname = self.tnode.abspath
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.debugname = debugname
self.abspath = abspath
self.compiled = File(self.filename + 'c')
self.assembly = File(self.filename + '.s')
self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath)
@ -228,9 +228,6 @@ env.Append(CPPPATH=Dir('.'))
for extra_dir in extras_dir_list:
env.Append(CPPPATH=Dir(extra_dir))
# Add a flag defining what THE_ISA should be for all compilation
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
# Workaround for bug in SCons version > 0.97d20071212
# Scons bug id: 2006 M5 Bug id: 308
for root, dirs, files in os.walk(base_dir, topdown=True):
@ -261,11 +258,38 @@ for extra_dir in extras_dir_list:
for opt in export_vars:
env.ConfigFile(opt)
def makeTheISA(source, target, env):
f = file(str(target[0]), 'w')
isas = [ src.get_contents() for src in source ]
target = env['TARGET_ISA']
def define(isa):
return isa.upper() + '_ISA'
def namespace(isa):
return isa[0].upper() + isa[1:].lower() + 'ISA'
print >>f, '#ifndef __CONFIG_THE_ISA_HH__'
print >>f, '#define __CONFIG_THE_ISA_HH__'
print >>f
for i,isa in enumerate(isas):
print >>f, '#define %s %d' % (define(isa), i + 1)
print >>f
print >>f, '#define THE_ISA %s' % (define(target))
print >>f, '#define TheISA %s' % (namespace(target))
print >>f
print >>f, '#endif // __CONFIG_THE_ISA_HH__'
env.Command('config/the_isa.hh', map(Value, all_isa_list), makeTheISA)
########################################################################
#
# 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.'''
@ -283,7 +307,7 @@ class DictImporter(object):
self.installed = set()
def find_module(self, fullname, path):
if fullname == 'defines':
if fullname == 'm5.defines':
return self
if fullname == 'm5.objects':
@ -293,7 +317,7 @@ class DictImporter(object):
return None
source = self.modules.get(fullname, None)
if source is not None and exists(source.snode.abspath):
if source is not None and fullname.startswith('m5.objects'):
return self
return None
@ -308,28 +332,31 @@ class DictImporter(object):
mod.__path__ = fullname.split('.')
return mod
if fullname == 'defines':
mod.__dict__['buildEnv'] = build_env
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.snode.abspath
mod.__file__ = source.abspath
exec file(source.snode.abspath, 'r') in mod.__dict__
exec file(source.abspath, 'r') in mod.__dict__
return mod
import m5.SimObject
import m5.params
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.
SimObject.fixed = True
importer = DictImporter(PySource.modules)
sys.meta_path[0:0] = [ importer ]
import m5
# 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:
@ -346,6 +373,12 @@ all_enums = m5.params.allEnums
all_params = {}
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
@ -365,13 +398,27 @@ depends = [ PySource.modules[dep].tnode for dep in module_depends ]
#
# Generate Python file containing a dict specifying the current
# build_env flags.
# buildEnv flags.
def makeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
build_env, hg_info = [ x.get_contents() for x in source ]
print >>f, "buildEnv = %s" % build_env
print >>f, "hgRev = '%s'" % hg_info
f.close()
code = m5.util.code_formatter()
code("""
import m5.internal
import m5.util
buildEnv = m5.util.SmartDict($build_env)
hgRev = '$hg_info'
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(str(target[0]))
defines_info = [ Value(build_env), Value(env['HG_INFO']) ]
# Generate a file with all of the compile options in it
@ -467,12 +514,7 @@ for name,simobj in sorted(sim_objects.iteritems()):
# Generate any parameter header files needed
params_i_files = []
for name,param in all_params.iteritems():
if isinstance(param, m5.params.VectorParamDesc):
ext = 'vptype'
else:
ext = 'ptype'
i_file = File('params/%s_%s.i' % (name, ext))
i_file = File('params/%s_%s.i' % (name, param.file_ext))
params_i_files.append(i_file)
env.Command(i_file, Value(name), createSwigParam)
env.Depends(i_file, depends)
@ -850,7 +892,7 @@ def objectifyPyFile(target, source, env):
dst = file(str(target[0]), 'w')
pysource = PySource.tnodes[source[0]]
compiled = compile(src, pysource.debugname, 'exec')
compiled = compile(src, pysource.abspath, 'exec')
marshalled = marshal.dumps(compiled)
compressed = zlib.compress(marshalled)
data = compressed

View file

@ -144,7 +144,7 @@ DtbFault::invoke(ThreadContext *tc)
// 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::NO_FAULT)) {
reqFlags.noneSet(Request::VPTE | Request::PREFETCH)) {
// set VA register with faulting address
tc->setMiscRegNoEffect(IPR_VA, vaddr);

View file

@ -36,7 +36,7 @@ namespace AlphaISA
{
void
ISA::serialize(std::ostream &os)
ISA::serialize(EventManager *em, std::ostream &os)
{
SERIALIZE_SCALAR(fpcr);
SERIALIZE_SCALAR(uniq);
@ -46,7 +46,7 @@ ISA::serialize(std::ostream &os)
}
void
ISA::unserialize(Checkpoint *cp, const std::string &section)
ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(fpcr);
UNSERIALIZE_SCALAR(uniq);

View file

@ -83,8 +83,9 @@ namespace AlphaISA
intr_flag = 0;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
void serialize(EventManager *em, std::ostream &os);
void unserialize(EventManager *em, Checkpoint *cp,
const std::string &section);
void reset(std::string core_name, ThreadID num_threads,
unsigned num_vpes, BaseCPU *_cpu)

View file

@ -627,7 +627,7 @@ decode OPCODE default Unknown::unknown() {
format MiscPrefetch {
0xf800: wh64({{ EA = Rb & ~ULL(63); }},
{{ xc->writeHint(EA, 64, memAccessFlags); }},
mem_flags = NO_FAULT,
mem_flags = PREFETCH,
inst_flags = [IsMemRef, IsDataPrefetch,
IsStore, MemWriteOp]);
}

View file

@ -548,7 +548,7 @@ def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
pf_flags = makeList(pf_flags)
inst_flags = makeList(inst_flags)
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
'IsDataPrefetch', 'MemReadOp']

View file

@ -105,6 +105,7 @@ class AlphaLinux : public Linux
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().
@ -125,6 +126,21 @@ class AlphaLinux : public Linux
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__

View file

@ -48,7 +48,8 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
int index = 0;
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
strcpy(name->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu");
@ -67,13 +68,15 @@ static SyscallReturn
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = process->getSyscallArg(tc, 0);
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<uint64_t> fpcr(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> fpcr(bufPtr);
// I don't think this exactly matches the HW FPCR
*fpcr = 0;
fpcr.copyOut(tc->getMemPort());
@ -94,13 +97,15 @@ static SyscallReturn
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = process->getSyscallArg(tc, 0);
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<uint64_t> fpcr(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> fpcr(bufPtr);
// I don't think this exactly matches the HW FPCR
fpcr.copyIn(tc->getMemPort());
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
@ -440,7 +445,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 315 */ SyscallDesc("munlock", unimplementedFunc),
/* 316 */ SyscallDesc("mlockall", unimplementedFunc),
/* 317 */ SyscallDesc("munlockall", unimplementedFunc),
/* 318 */ SyscallDesc("sysinfo", unimplementedFunc),
/* 318 */ SyscallDesc("sysinfo", sysinfoFunc<AlphaLinux>),
/* 319 */ SyscallDesc("_sysctl", unimplementedFunc),
/* 320 */ SyscallDesc("was sys_idle", unimplementedFunc),
/* 321 */ SyscallDesc("oldumount", unimplementedFunc),

View file

@ -193,10 +193,10 @@ AlphaLiveProcess::startup()
}
AlphaISA::IntReg
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int i)
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i);
return tc->readIntReg(FirstArgumentReg + i++);
}
void

View file

@ -44,7 +44,7 @@ class AlphaLiveProcess : public LiveProcess
void argsInit(int intSize, int pageSize);
public:
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int i);
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};

View file

@ -45,7 +45,8 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, 0));
int index = 0;
TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, index));
strcpy(name->sysname, "OSF1");
strcpy(name->nodename, "m5.eecs.umich.edu");
@ -62,35 +63,36 @@ static SyscallReturn
getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = process->getSyscallArg(tc, 0);
unsigned nbytes = process->getSyscallArg(tc, 2);
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<uint32_t> max_cpu(process->getSyscallArg(tc, 1));
TypedBufferArg<uint32_t> max_cpu(bufPtr);
*max_cpu = htog((uint32_t)process->numCpus());
max_cpu.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_CPUS_IN_BOX: {
TypedBufferArg<uint32_t> cpus_in_box(process->getSyscallArg(tc, 1));
TypedBufferArg<uint32_t> cpus_in_box(bufPtr);
*cpus_in_box = htog((uint32_t)process->numCpus());
cpus_in_box.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_PHYSMEM: {
TypedBufferArg<uint64_t> physmem(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> physmem(bufPtr);
*physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
physmem.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_CPU_INFO: {
TypedBufferArg<AlphaTru64::cpu_info>
infop(process->getSyscallArg(tc, 1));
TypedBufferArg<AlphaTru64::cpu_info> infop(bufPtr);
infop->current_cpu = htog(0);
infop->cpus_in_box = htog(process->numCpus());
@ -107,14 +109,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
case AlphaTru64::GSI_PROC_TYPE: {
TypedBufferArg<uint64_t> proc_type(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> proc_type(bufPtr);
*proc_type = htog((uint64_t)11);
proc_type.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_PLATFORM_NAME: {
BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes);
BufferArg bufArg(bufPtr, nbytes);
strncpy((char *)bufArg.bufferPtr(),
"COMPAQ Professional Workstation XP1000",
nbytes);
@ -123,7 +125,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
case AlphaTru64::GSI_CLK_TCK: {
TypedBufferArg<uint64_t> clk_hz(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> clk_hz(bufPtr);
*clk_hz = htog((uint64_t)1024);
clk_hz.copyOut(tc->getMemPort());
return 1;
@ -142,12 +144,13 @@ static SyscallReturn
setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = process->getSyscallArg(tc, 0);
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, 1));
process->getSyscallArg(tc, index));
break;
default:
@ -165,17 +168,19 @@ tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
using namespace std;
int id = process->getSyscallArg(tc, 0); // table ID
int index = process->getSyscallArg(tc, 1); // index into table
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, 3); // number of elements
int lel = process->getSyscallArg(tc, 4); // expected element size
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<Tru64::tbl_sysinfo> elp(process->getSyscallArg(tc, 2));
TypedBufferArg<Tru64::tbl_sysinfo> elp(bufPtr);
const int clk_hz = one_million;
elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));

View file

@ -99,6 +99,7 @@ class AlphaTru64 : public Tru64
static const unsigned TIOCISATTY_ = 0x2000745e;
static const unsigned TIOCGETS_ = 0x402c7413;
static const unsigned TIOCGETA_ = 0x40127417;
static const unsigned TCSETAW_ = 0x80147419;
//@}
//@{

View file

@ -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'

View file

@ -1,4 +1,4 @@
# Copyright (c) 2005 The Regents of The University of Michigan
# Copyright (c) 2009 ARM Limited
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -24,20 +24,12 @@
# (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
# Authors: Ali Saidi
import os
from m5.params import *
# import the m5 compile options
import defines
from System import System
# make a SmartDict out of the build options for our local use
import smartdict
build_env = smartdict.SmartDict()
build_env.update(defines.m5_build_env)
# make a SmartDict out of the OS environment too
env = smartdict.SmartDict()
env.update(os.environ)
class ArmSystem(System):
type = 'ArmSystem'

View file

@ -1,6 +1,7 @@
# -*- mode:python -*-
# Copyright (c) 2007-2008 The Florida State University
# Copyright (c) 2009 ARM Limited
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -27,6 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Stephen Hines
# Ali Saidi
Import('*')
@ -43,15 +45,20 @@ if env['TARGET_ISA'] == 'arm':
Source('pagetable.cc')
Source('tlb.cc')
Source('vtophys.cc')
Source('utility.cc')
SimObject('ArmNativeTrace.py')
SimObject('ArmTLB.py')
TraceFlag('Arm')
TraceFlag('Faults', "Trace Exceptions, interrupts, svc/swi")
if env['FULL_SYSTEM']:
#Insert Full-System Files Here
pass
Source('interrupts.cc')
Source('stacktrace.cc')
Source('system.cc')
SimObject('ArmInterrupts.py')
SimObject('ArmSystem.py')
else:
Source('process.cc')
Source('linux/linux.cc')

View file

@ -26,488 +26,114 @@
* (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
* Stephen Hines
* Authors: Ali Saidi
* Gabe Black
*/
#include "arch/arm/faults.hh"
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace ArmISA
{
FaultName MachineCheckFault::_name = "Machine Check";
FaultVect MachineCheckFault::_vect = 0x0401;
FaultStat MachineCheckFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<Reset>::vals =
{"reset", 0x00, MODE_SVC, 0, 0, true, true};
FaultName AlignmentFault::_name = "Alignment";
FaultVect AlignmentFault::_vect = 0x0301;
FaultStat AlignmentFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<UndefinedInstruction>::vals =
{"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ;
FaultName ResetFault::_name = "Reset Fault";
#if FULL_SYSTEM
FaultVect ResetFault::_vect = 0xBFC00000;
#else
FaultVect ResetFault::_vect = 0x001;
#endif
FaultStat ResetFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<SupervisorCall>::vals =
{"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false};
FaultName AddressErrorFault::_name = "Address Error";
FaultVect AddressErrorFault::_vect = 0x0180;
FaultStat AddressErrorFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<PrefetchAbort>::vals =
{"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false};
FaultName StoreAddressErrorFault::_name = "Store Address Error";
FaultVect StoreAddressErrorFault::_vect = 0x0180;
FaultStat StoreAddressErrorFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<DataAbort>::vals =
{"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false};
template<> ArmFaultBase::FaultVals ArmFault<Interrupt>::vals =
{"IRQ", 0x18, MODE_IRQ, 4, 4, true, false};
FaultName SystemCallFault::_name = "Syscall";
FaultVect SystemCallFault::_vect = 0x0180;
FaultStat SystemCallFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<FastInterrupt>::vals =
{"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault";
FaultVect CoprocessorUnusableFault::_vect = 0x180;
FaultStat CoprocessorUnusableFault::_count;
Addr
ArmFaultBase::getVector(ThreadContext *tc)
{
// ARM ARM B1-3
FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault";
FaultVect ReservedInstructionFault::_vect = 0x0180;
FaultStat ReservedInstructionFault::_count;
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;
FaultName ThreadFault::_name = "Thread Fault";
FaultVect ThreadFault::_vect = 0x00F1;
FaultStat ThreadFault::_count;
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
FaultVect ArithmeticFault::_vect = 0x180;
FaultStat ArithmeticFault::_count;
FaultName UnimplementedOpcodeFault::_name = "opdec";
FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
FaultStat UnimplementedOpcodeFault::_count;
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0180;
FaultStat InterruptFault::_count;
FaultName TrapFault::_name = "Trap";
FaultVect TrapFault::_vect = 0x0180;
FaultStat TrapFault::_count;
FaultName BreakpointFault::_name = "Breakpoint";
FaultVect BreakpointFault::_vect = 0x0180;
FaultStat BreakpointFault::_count;
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
FaultVect ItbInvalidFault::_vect = 0x0180;
FaultStat ItbInvalidFault::_count;
FaultName ItbPageFault::_name = "itbmiss";
FaultVect ItbPageFault::_vect = 0x0181;
FaultStat ItbPageFault::_count;
FaultName ItbMissFault::_name = "itbmiss";
FaultVect ItbMissFault::_vect = 0x0181;
FaultStat ItbMissFault::_count;
FaultName ItbAcvFault::_name = "iaccvio";
FaultVect ItbAcvFault::_vect = 0x0081;
FaultStat ItbAcvFault::_count;
FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)";
FaultVect ItbRefillFault::_vect = 0x0180;
FaultStat ItbRefillFault::_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 = "dfault";
FaultVect DtbPageFault::_vect = 0x0381;
FaultStat DtbPageFault::_count;
FaultName DtbAcvFault::_name = "dfault";
FaultVect DtbAcvFault::_vect = 0x0381;
FaultStat DtbAcvFault::_count;
FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)";
FaultVect DtbInvalidFault::_vect = 0x0180;
FaultStat DtbInvalidFault::_count;
FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)";
FaultVect DtbRefillFault::_vect = 0x0180;
FaultStat DtbRefillFault::_count;
FaultName TLBModifiedFault::_name = "TLB Modified Exception";
FaultVect TLBModifiedFault::_vect = 0x0180;
FaultStat TLBModifiedFault::_count;
FaultName FloatEnableFault::_name = "float_enable_fault";
FaultVect FloatEnableFault::_vect = 0x0581;
FaultStat FloatEnableFault::_count;
FaultName IntegerOverflowFault::_name = "Integer Overflow Fault";
FaultVect IntegerOverflowFault::_vect = 0x0501;
FaultStat IntegerOverflowFault::_count;
FaultName DspStateDisabledFault::_name = "DSP Disabled Fault";
FaultVect DspStateDisabledFault::_vect = 0x001a;
FaultStat DspStateDisabledFault::_count;
}
#if FULL_SYSTEM
void ArmFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
void
ArmFaultBase::invoke(ThreadContext *tc)
{
tc->setPC(HandlerBase);
tc->setNextPC(HandlerBase+sizeof(MachInst));
tc->setNextNPC(HandlerBase+2*sizeof(MachInst));
// ARM ARM B1.6.3
FaultBase::invoke(tc);
countStat()++;
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
tc->readIntReg(INTREG_CONDCODES);
cpsr.mode = nextMode();
cpsr.it1 = cpsr.it2 = 0;
cpsr.j = 0;
if (sctlr.te)
cpsr.t = 1;
cpsr.a = cpsr.a | abortDisable();
cpsr.f = cpsr.f | fiqDisable();
cpsr.i = 1;
tc->setMiscReg(MISCREG_CPSR, cpsr);
tc->setIntReg(INTREG_LR, tc->readPC() +
(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");
}
DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x\n", name(), cpsr,
tc->readPC(), tc->readIntReg(INTREG_LR));
tc->setPC(getVector(tc));
tc->setNextPC(getVector(tc) + cpsr.t ? 2 : 4 );
}
void ArmFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode)
{
// modify SRS Ctl - Save CSS, put ESS into CSS
MiscReg stat = tc->readMiscReg(ArmISA::Status);
if(bits(stat,Status_EXL) != 1 && bits(stat,Status_BEV) != 1)
{
// SRS Ctl is modified only if Status_EXL and Status_BEV are not set
MiscReg srs = tc->readMiscReg(ArmISA::SRSCtl);
uint8_t CSS,ESS;
CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO);
ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO);
// Move CSS to PSS
replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS);
// Move ESS to CSS
replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS);
tc->setMiscRegNoEffect(ArmISA::SRSCtl,srs);
//tc->setShadowSet(ESS);
}
// set EXL bit (don't care if it is already set!)
replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1);
tc->setMiscRegNoEffect(ArmISA::Status,stat);
// write EPC
// warn("Set EPC to %x\n",tc->readPC());
// CHECK ME or FIXME or FIX ME or POSSIBLE HACK
// Check to see if the exception occurred in the branch delay slot
DPRINTF(Arm,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC());
int C_BD=0;
if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){
tc->setMiscRegNoEffect(ArmISA::EPC,tc->readPC()-sizeof(MachInst));
// In the branch delay slot? set CAUSE_31
C_BD = 1;
} else {
tc->setMiscRegNoEffect(ArmISA::EPC,tc->readPC());
// In the branch delay slot? reset CAUSE_31
C_BD = 0;
}
// Set Cause_EXCCODE field
MiscReg cause = tc->readMiscReg(ArmISA::Cause);
replaceBits(cause,Cause_EXCCODE_HI,Cause_EXCCODE_LO,ExcCode);
replaceBits(cause,Cause_BD_HI,Cause_BD_LO,C_BD);
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,0);
tc->setMiscRegNoEffect(ArmISA::Cause,cause);
}
void ArithmeticFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0xC);
// Set new PC
Addr HandlerBase;
MiscReg stat = tc->readMiscReg(ArmISA::Status);
// Here, the handler is dependent on BEV, which is not modified by setExceptionState()
if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase);
}else{
HandlerBase = 0xBFC00200;
}
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
}
void StoreAddressErrorFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0x5);
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void TrapFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
// warn("%s encountered.\n", name());
setExceptionState(tc,0xD);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void BreakpointFault::invoke(ThreadContext *tc)
{
setExceptionState(tc,0x9);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void DtbInvalidFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
// warn("%s encountered.\n", name());
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
setExceptionState(tc,0x3);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void AddressErrorFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0x4);
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
}
void ItbInvalidFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0x2);
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
DPRINTF(Arm,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void ItbRefillFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered (%x).\n", name(),BadVAddr);
Addr HandlerBase;
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
MiscReg stat = tc->readMiscReg(ArmISA::Status);
// Since handler depends on EXL bit, must check EXL bit before setting it!!
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
}else{
HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000
}
setExceptionState(tc,0x2);
setHandlerPC(HandlerBase,tc);
}
void DtbRefillFault::invoke(ThreadContext *tc)
{
// Set new PC
DPRINTF(Arm,"%s encountered.\n", name());
Addr HandlerBase;
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
MiscReg stat = tc->readMiscReg(ArmISA::Status);
// Since handler depends on EXL bit, must check EXL bit before setting it!!
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
}else{
HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000
}
setExceptionState(tc,0x3);
setHandlerPC(HandlerBase,tc);
}
void TLBModifiedFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setExceptionState(tc,0x1);
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void SystemCallFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0x8);
// Set new PC
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Exception Handler At: %x \n",HandlerBase);
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
}
void InterruptFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0x0A);
Addr HandlerBase;
uint8_t IV = bits(tc->readMiscRegNoEffect(ArmISA::Cause),Cause_IV);
if (IV)// Offset 200 for release 2
HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(ArmISA::EBase);
else//Ofset at 180 for release 1
HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase);
setHandlerPC(HandlerBase,tc);
#endif
}
#endif // FULL_SYSTEM
void ResetFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
DPRINTF(Arm,"%s encountered.\n", name());
/* All reset activity must be invoked from here */
tc->setPC(vect());
tc->setNextPC(vect()+sizeof(MachInst));
tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst));
DPRINTF(Arm,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC());
#endif
// return via SUBS pc, lr, xxx; rfe, movs, ldm
// Set Coprocessor 1 (Floating Point) To Usable
//tc->setMiscReg(ArmISA::Status, ArmISA::Status | 0x20000000);
}
void ReservedInstructionFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0x0A);
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
#else
panic("%s encountered.\n", name());
#endif
}
void ThreadFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
panic("%s encountered.\n", name());
}
void DspStateDisabledFault::invoke(ThreadContext *tc)
{
DPRINTF(Arm,"%s encountered.\n", name());
panic("%s encountered.\n", name());
}
void CoprocessorUnusableFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
DPRINTF(Arm,"%s encountered.\n", name());
setExceptionState(tc,0xb);
/* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */
MiscReg cause = tc->readMiscReg(ArmISA::Cause);
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID);
tc->setMiscRegNoEffect(ArmISA::Cause,cause);
Addr HandlerBase;
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
setHandlerPC(HandlerBase,tc);
// warn("Status: %x, Cause: %x\n",tc->readMiscReg(ArmISA::Status),tc->readMiscReg(ArmISA::Cause));
#else
warn("%s (CP%d) encountered.\n", name(), coProcID);
#endif
}
} // namespace ArmISA

View file

@ -26,548 +26,79 @@
* (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
* Stephen Hines
* Authors: Ali Saidi
* Gabe Black
*/
#ifndef __ARM_FAULTS_HH__
#define __ARM_FAULTS_HH__
#include "arch/arm/types.hh"
#include "config/full_system.hh"
#include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
namespace ArmISA
{
typedef const Addr FaultVect;
typedef const Addr FaultOffset;
class ArmFault : public FaultBase
class ArmFaultBase : public FaultBase
{
protected:
virtual bool skipFaultingInstruction() {return false;}
virtual bool setRestartAddress() {return true;}
Addr getVector(ThreadContext *tc);
public:
Addr BadVAddr;
Addr EntryHi_Asid;
Addr EntryHi_VPN2;
Addr EntryHi_VPN2X;
Addr Context_BadVPN2;
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;
};
#if FULL_SYSTEM
void invoke(ThreadContext * tc) {};
void setExceptionState(ThreadContext *,uint8_t);
void setHandlerPC(Addr,ThreadContext *);
void invoke(ThreadContext *tc);
#endif
virtual FaultVect vect() = 0;
virtual FaultStat & countStat() = 0;
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;
};
class MachineCheckFault : public ArmFault
{
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 isMachineCheckFault() {return true;}
};
class NonMaskableInterrupt : public ArmFault
{
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 isNonMaskableInterrupt() {return true;}
};
class AlignmentFault : public ArmFault
{
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() {return true;}
};
class AddressErrorFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class StoreAddressErrorFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class UnimplementedOpcodeFault : public ArmFault
{
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 TLBRefillIFetchFault : public ArmFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class TLBInvalidIFetchFault : public ArmFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class NDtbMissFault : public ArmFault
{
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 PDtbMissFault : public ArmFault
{
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 DtbPageFault : public ArmFault
{
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 DtbAcvFault : public ArmFault
{
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 CacheErrorFault : public ArmFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;
}
static inline Fault genAlignmentFault()
{
return new AlignmentFault;
}
class ResetFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class SystemCallFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class SoftResetFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class DebugSingleStep : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class DebugInterrupt : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class CoprocessorUnusableFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
int coProcID;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
CoprocessorUnusableFault(int _procid){ coProcID = _procid;}
};
class ReservedInstructionFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class ThreadFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class ArithmeticFault : public ArmFault
template<typename T>
class ArmFault : public ArmFaultBase
{
protected:
bool skipFaultingInstruction() {return true;}
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
static FaultVals vals;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
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 InterruptFault : public ArmFault
{
protected:
bool setRestartAddress() {return false;}
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
class Reset : public ArmFault<Reset> {};
class UndefinedInstruction : public ArmFault<UndefinedInstruction> {};
class SupervisorCall : public ArmFault<SupervisorCall> {};
class PrefetchAbort : public ArmFault<PrefetchAbort> {};
class DataAbort : public ArmFault<DataAbort> {};
class Interrupt : public ArmFault<Interrupt> {};
class FastInterrupt : public ArmFault<FastInterrupt> {};
//void invoke(ThreadContext * tc);
};
class TrapFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class BreakpointFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class ItbRefillFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class DtbRefillFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class ItbPageFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class ItbInvalidFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class TLBModifiedFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class DtbInvalidFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class FloatEnableFault : public ArmFault
{
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 ItbMissFault : public ArmFault
{
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 ItbAcvFault : public ArmFault
{
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 IntegerOverflowFault : public ArmFault
{
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 DspStateDisabledFault : public ArmFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
} // ArmISA namespace

View file

@ -84,33 +84,20 @@ class MicroMemOp : public MicroIntOp
*/
class ArmMacroMemoryOp : public PredMacroOp
{
protected:
protected:
/// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags;
uint32_t reglist;
uint32_t ones;
uint32_t puswl,
prepost,
up,
psruser,
writeback,
loadop;
ArmMacroMemoryOp(const char *mnem, ExtMachInst _machInst,
OpClass __opClass)
: PredMacroOp(mnem, _machInst, __opClass),
memAccessFlags(0),
reglist(machInst.regList), ones(0),
puswl(machInst.puswl),
prepost(machInst.puswl.prepost),
up(machInst.puswl.up),
psruser(machInst.puswl.psruser),
writeback(machInst.puswl.writeback),
loadop(machInst.puswl.loadOp)
: PredMacroOp(mnem, _machInst, __opClass), memAccessFlags(0),
reglist(machInst.regList), ones(0)
{
ones = number_of_ones(reglist);
numMicroops = ones + writeback + 1;
numMicroops = ones + machInst.puswl.writeback + 1;
// Remember that writeback adds a uop
microOps = new StaticInstPtr[numMicroops];
}
@ -121,7 +108,7 @@ class ArmMacroMemoryOp : public PredMacroOp
*/
class ArmMacroFPAOp : public PredMacroOp
{
protected:
protected:
uint32_t puswl,
prepost,
up,
@ -150,7 +137,7 @@ class ArmMacroFPAOp : public PredMacroOp
*/
class ArmMacroFMOp : public PredMacroOp
{
protected:
protected:
uint32_t punwl,
prepost,
up,

View file

@ -27,8 +27,10 @@
* Authors: Stephen Hines
*/
#include "arch/arm/faults.hh"
#include "arch/arm/insts/static_inst.hh"
#include "base/condcodes.hh"
#include "base/cprintf.hh"
#include "base/loader/symtab.hh"
namespace ArmISA
@ -62,7 +64,7 @@ ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
else
return (base << (32 - shamt)) | (base >> shamt);
default:
fprintf(stderr, "Unhandled shift type\n");
ccprintf(std::cerr, "Unhandled shift type\n");
exit(1);
break;
}
@ -101,7 +103,7 @@ ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
else
return (base << (32 - shamt)) | (base >> shamt);
default:
fprintf(stderr, "Unhandled shift type\n");
ccprintf(std::cerr, "Unhandled shift type\n");
exit(1);
break;
}
@ -141,7 +143,7 @@ ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
else
return (base >> (shamt - 1)) & 1;
default:
fprintf(stderr, "Unhandled shift type\n");
ccprintf(std::cerr, "Unhandled shift type\n");
exit(1);
break;
}
@ -182,7 +184,7 @@ ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
shamt = 32;
return (base >> (shamt - 1)) & 1;
default:
fprintf(stderr, "Unhandled shift type\n");
ccprintf(std::cerr, "Unhandled shift type\n");
exit(1);
break;
}

View file

@ -74,6 +74,56 @@ class ArmStaticInst : public StaticInst
void printDataInst(std::ostream &os, bool withImm) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
static uint32_t
cpsrWriteByInstr(CPSR cpsr, uint32_t val,
uint8_t byteMask, bool affectState)
{
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);
bitMask = bitMask | mask(5);
}
if (affectState)
bitMask = bitMask | (1 << 5);
}
return ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
}
static 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));
}
};
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 ARM Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,15 +24,14 @@
* 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
*/
/*
* AST.C
*
* Description: See AST.hh
*
* $Id$
*
*/
#include "mem/slicc/ast/AST.hh"
#include "arch/arm/interrupts.hh"
ArmISA::Interrupts *
ArmInterruptsParams::create()
{
return new ArmISA::Interrupts(this);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2006 The Regents of The University of Michigan
* Copyright (c) 2009 ARM Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,59 +25,97 @@
* 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
*/
/*
* LiteralExprAST.hh
*
* Description:
*
* $Id: LiteralExprAST.hh,v 3.1 2001/12/12 01:00:20 milo Exp $
*
*/
#ifndef __ARCH_ARM_INTERRUPT_HH__
#define __ARCH_ARM_INTERRUPT_HH__
#ifndef LITERALEXPRAST_H
#define LITERALEXPRAST_H
#include "arch/arm/faults.hh"
#include "arch/arm/isa_traits.hh"
#include "arch/arm/registers.hh"
#include "cpu/thread_context.hh"
#include "params/ArmInterrupts.hh"
#include "sim/sim_object.hh"
#include "mem/slicc/slicc_global.hh"
#include "mem/slicc/ast/ExprAST.hh"
class LiteralExprAST : public ExprAST {
public:
// Constructors
LiteralExprAST(string* lit_ptr, string type) : ExprAST() { m_lit_ptr = lit_ptr; m_type = type; }
// Destructor
~LiteralExprAST() { delete m_lit_ptr; }
// Public Methods
Type* generate(string& code) const;
void print(ostream& out) const { out << "[Literal: " << *m_lit_ptr << "]"; }
private:
// Private Methods
// Private copy constructor and assignment operator
LiteralExprAST(const LiteralExprAST& obj);
LiteralExprAST& operator=(const LiteralExprAST& obj);
// Data Members (m_ prefix)
string* m_lit_ptr;
string m_type;
};
// Output operator declaration
ostream& operator<<(ostream& out, const LiteralExprAST& obj);
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const LiteralExprAST& obj)
namespace ArmISA
{
obj.print(out);
out << flush;
return out;
}
#endif //LITERALEXPRAST_H
class Interrupts : public SimObject
{
private:
BaseCPU * cpu;
uint64_t intStatus;
public:
void
setCPU(BaseCPU * _cpu)
{
cpu = _cpu;
}
typedef ArmInterruptsParams Params;
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
Interrupts(Params * p) : SimObject(p), cpu(NULL)
{
clearAll();
}
void
post(int int_num, int index)
{
}
void
clear(int int_num, int index)
{
}
void
clearAll()
{
intStatus = 0;
}
bool
checkInterrupts(ThreadContext *tc) const
{
return intStatus;
}
Fault
getInterrupt(ThreadContext *tc)
{
warn_once("ARM Interrupts not handled\n");
return NoFault;
}
void
updateIntrInfo(ThreadContext *tc)
{
}
void
serialize(std::ostream &os)
{
}
void
unserialize(Checkpoint *cp, const std::string &section)
{
}
};
} // namespace ARM_ISA
#endif // __ARCH_ARM_INTERRUPT_HH__

337
src/arch/arm/intregs.hh Normal file
View file

@ -0,0 +1,337 @@
/*
* 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 <assert.h>
#ifndef __ARCH_ARM_INTREGS_HH__
#define __ARCH_ARM_INTREGS_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_RHI,
INTREG_RLO,
INTREG_CONDCODES,
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 inline IntRegIndex
intRegForceUser(unsigned index)
{
assert(index < NUM_ARCH_INTREGS);
return index == 15 ? (IntRegIndex)15 : (IntRegIndex)(index + NUM_INTREGS);
}
}
#endif

View file

@ -44,6 +44,38 @@ namespace ArmISA
{
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()
@ -52,6 +84,15 @@ namespace ArmISA
CPSR cpsr = 0;
cpsr.mode = MODE_USER;
miscRegs[MISCREG_CPSR] = cpsr;
updateRegMap(cpsr);
SCTLR sctlr = 0;
sctlr.nmfi = 1;
sctlr.rao1 = 1;
sctlr.rao2 = 1;
sctlr.rao3 = 1;
sctlr.rao4 = 1;
//XXX We need to initialize the rest of the state.
}
@ -59,34 +100,94 @@ namespace ArmISA
readMiscRegNoEffect(int misc_reg)
{
assert(misc_reg < NumMiscRegs);
if (misc_reg == MISCREG_SPSR) {
CPSR cpsr = miscRegs[MISCREG_CPSR];
switch (cpsr.mode) {
case MODE_USER:
return miscRegs[MISCREG_SPSR];
case MODE_FIQ:
return miscRegs[MISCREG_SPSR_FIQ];
case MODE_IRQ:
return miscRegs[MISCREG_SPSR_IRQ];
case MODE_SVC:
return miscRegs[MISCREG_SPSR_SVC];
case MODE_MON:
return miscRegs[MISCREG_SPSR_MON];
case MODE_ABORT:
return miscRegs[MISCREG_SPSR_ABT];
case MODE_UNDEFINED:
return miscRegs[MISCREG_SPSR_UND];
default:
return miscRegs[MISCREG_SPSR];
}
}
return miscRegs[misc_reg];
}
MiscReg
readMiscReg(int misc_reg, ThreadContext *tc)
{
assert(misc_reg < NumMiscRegs);
return miscRegs[misc_reg];
return readMiscRegNoEffect(misc_reg);
}
void
setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
assert(misc_reg < NumMiscRegs);
if (misc_reg == MISCREG_SPSR) {
CPSR cpsr = miscRegs[MISCREG_CPSR];
switch (cpsr.mode) {
case MODE_USER:
miscRegs[MISCREG_SPSR] = val;
return;
case MODE_FIQ:
miscRegs[MISCREG_SPSR_FIQ] = val;
return;
case MODE_IRQ:
miscRegs[MISCREG_SPSR_IRQ] = val;
return;
case MODE_SVC:
miscRegs[MISCREG_SPSR_SVC] = val;
return;
case MODE_MON:
miscRegs[MISCREG_SPSR_MON] = val;
return;
case MODE_ABORT:
miscRegs[MISCREG_SPSR_ABT] = val;
return;
case MODE_UNDEFINED:
miscRegs[MISCREG_SPSR_UND] = val;
return;
default:
miscRegs[MISCREG_SPSR] = val;
return;
}
}
miscRegs[misc_reg] = val;
}
void
setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{
assert(misc_reg < NumMiscRegs);
miscRegs[misc_reg] = val;
if (misc_reg == MISCREG_CPSR) {
updateRegMap(val);
}
return setMiscRegNoEffect(misc_reg, val);
}
int
flattenIntIndex(int reg)
{
return reg;
assert(reg >= 0);
if (reg < NUM_ARCH_INTREGS) {
return intRegMap[reg];
} else if (reg < NUM_INTREGS) {
return reg;
} else {
reg -= NUM_INTREGS;
assert(reg < NUM_ARCH_INTREGS);
return reg;
}
}
int
@ -95,9 +196,10 @@ namespace ArmISA
return reg;
}
void serialize(std::ostream &os)
void serialize(EventManager *em, std::ostream &os)
{}
void unserialize(Checkpoint *cp, const std::string &section)
void unserialize(EventManager *em, Checkpoint *cp,
const std::string &section)
{}
ISA()

View file

@ -38,14 +38,18 @@ 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_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 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_4 opcode4;

View file

@ -51,20 +51,25 @@ format DataOp {
resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
Rd = (uint32_t)(resTemp & 0xffffffff);
Rn = (uint32_t)(resTemp >> 32);
}});
0x5: WarnUnimpl::smlal();
}}, llbit);
0x5: smlal({{
resTemp = ((int64_t)Rm) * ((int64_t)Rs);
resTemp += (((uint64_t)Rn) << 32) | ((uint64_t)Rd);
Rd = (uint32_t)(resTemp & 0xffffffff);
Rn = (uint32_t)(resTemp >> 32);
}}, llbit);
0x6: smull({{
resTemp = ((int64_t)(int32_t)Rm)*
((int64_t)(int32_t)Rs);
Rd = (int32_t)(resTemp & 0xffffffff);
Rn = (int32_t)(resTemp >> 32);
}});
}}, llbit);
0x7: umlal({{
resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd);
Rd = (uint32_t)(resTemp & 0xffffffff);
Rn = (uint32_t)(resTemp >> 32);
}});
}}, llbit);
}
1: decode PUBWL {
0x10: WarnUnimpl::swp();
@ -91,9 +96,9 @@ format DataOp {
0x2: sub({{ Rd = resTemp = Rn - op2; }}, sub);
0x3: rsb({{ Rd = resTemp = op2 - Rn; }}, rsb);
0x4: add({{ Rd = resTemp = Rn + op2; }}, add);
0x5: adc({{ Rd = resTemp = Rn + op2 + Cpsr<29:>; }}, add);
0x6: sbc({{ Rd = resTemp = Rn - op2 - !Cpsr<29:>; }}, sub);
0x7: rsc({{ Rd = resTemp = op2 - Rn - !Cpsr<29:>; }}, rsb);
0x5: adc({{ Rd = resTemp = Rn + op2 + CondCodes<29:>; }}, add);
0x6: sbc({{ Rd = resTemp = Rn - op2 - !CondCodes<29:>; }}, sub);
0x7: rsc({{ Rd = resTemp = op2 - Rn - !CondCodes<29:>; }}, rsb);
0x8: tst({{ resTemp = Rn & op2; }});
0x9: teq({{ resTemp = Rn ^ op2; }});
0xa: cmp({{ resTemp = Rn - op2; }}, sub);
@ -105,10 +110,37 @@ format DataOp {
}
1: decode MISC_OPCODE {
0x0: decode OPCODE {
0x8: WarnUnimpl::mrs_cpsr();
0x9: WarnUnimpl::msr_cpsr();
0xa: WarnUnimpl::mrs_spsr();
0xb: WarnUnimpl::msr_spsr();
0x8: PredOp::mrs_cpsr({{
Rd = (Cpsr | CondCodes) & 0xF8FF03DF;
}});
0x9: decode USEIMM {
// The mask field is the same as the RN index.
0: PredOp::msr_cpsr_reg({{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes,
Rm, RN, false);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
}});
1: PredImmOp::msr_cpsr_imm({{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes,
rotated_imm, RN, false);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
}});
}
0xa: PredOp::mrs_spsr({{ Rd = Spsr; }});
0xb: decode USEIMM {
// The mask field is the same as the RN index.
0: PredOp::msr_spsr_reg({{
Spsr = spsrWriteByInstr(Spsr, Rm, RN, false);
}});
1: PredImmOp::msr_spsr_imm({{
Spsr = spsrWriteByInstr(Spsr, rotated_imm,
RN, false);
}});
}
}
0x1: decode OPCODE {
0x9: BranchExchange::bx({{ }});
@ -129,28 +161,32 @@ format DataOp {
0xb: WarnUnimpl::qdsub();
}
0x8: decode OPCODE {
0x8: WarnUnimpl::smlabb();
0x8: smlabb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>) + Rd; }}, overflow);
0x9: WarnUnimpl::smlalbb();
0xa: WarnUnimpl::smlawb();
0xb: WarnUnimpl::smulbb();
0xb: smulbb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>); }}, none);
}
0xa: decode OPCODE {
0x8: WarnUnimpl::smlatb();
0x9: WarnUnimpl::smulwb();
0x8: smlatb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>) + Rd; }}, overflow);
0x9: smulwb({{
Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<15:0>), 47, 16);
}}, none);
0xa: WarnUnimpl::smlaltb();
0xb: WarnUnimpl::smultb();
0xb: smultb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>); }}, none);
}
0xc: decode OPCODE {
0x8: WarnUnimpl::smlabt();
0x8: smlabt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>) + Rd; }}, overflow);
0x9: WarnUnimpl::smlawt();
0xa: WarnUnimpl::smlalbt();
0xb: WarnUnimpl::smulbt();
0xb: smulbt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>); }}, none);
}
0xe: decode OPCODE {
0x8: WarnUnimpl::smlatt();
0x9: WarnUnimpl::smulwt();
0x8: smlatt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>) + Rd; }}, overflow);
0x9: smulwt({{
Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<31:16>), 47, 16);
}}, none);
0xa: WarnUnimpl::smlaltt();
0xb: WarnUnimpl::smultt();
0xb: smultt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>); }}, none);
}
}
}
@ -163,9 +199,15 @@ format DataOp {
0x2: subi({{ Rd = resTemp = Rn - rotated_imm; }}, sub);
0x3: rsbi({{ Rd = resTemp = rotated_imm - Rn; }}, rsb);
0x4: addi({{ Rd = resTemp = Rn + rotated_imm; }}, add);
0x5: adci({{ Rd = resTemp = Rn + rotated_imm + Cpsr<29:>; }}, add);
0x6: sbci({{ Rd = resTemp = Rn -rotated_imm - !Cpsr<29:>; }}, sub);
0x7: rsci({{ Rd = resTemp = rotated_imm - Rn - !Cpsr<29:>;}}, rsb);
0x5: adci({{
Rd = resTemp = Rn + rotated_imm + CondCodes<29:>;
}}, add);
0x6: sbci({{
Rd = resTemp = Rn -rotated_imm - !CondCodes<29:>;
}}, sub);
0x7: rsci({{
Rd = resTemp = rotated_imm - Rn - !CondCodes<29:>;
}}, rsb);
0x8: tsti({{ resTemp = Rn & rotated_imm; }});
0x9: teqi({{ resTemp = Rn ^ rotated_imm; }});
0xa: cmpi({{ resTemp = Rn - rotated_imm; }}, sub);
@ -178,11 +220,27 @@ format DataOp {
}
1: decode OPCODE {
// The following two instructions aren't supposed to be defined
0x8: WarnUnimpl::undefined_instruction();
0x9: WarnUnimpl::undefined_instruction();
0xa: WarnUnimpl::mrs_i_cpsr();
0xb: WarnUnimpl::mrs_i_spsr();
0x8: DataOp::movw({{ Rd = IMMED_11_0 | (RN << 12) ; }});
0x9: decode RN {
0: decode IMM {
0: PredImmOp::nop({{ ; }});
1: WarnUnimpl::yield();
2: WarnUnimpl::wfe();
3: WarnUnimpl::wfi();
4: WarnUnimpl::sev();
}
default: PredImmOp::msr_i_cpsr({{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes,
rotated_imm, RN, false);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
}});
}
0xa: PredOp::movt({{ Rd = IMMED_11_0 << 16 | RN << 28 | Rd<15:0>; }});
0xb: PredImmOp::msr_i_spsr({{
Spsr = spsrWriteByInstr(Spsr, rotated_imm, RN, false);
}});
}
}
0x2: AddrMode2::addrMode2(Disp, disp);
@ -324,77 +382,79 @@ format DataOp {
}
}
0x7: decode OPCODE_24 {
0: decode CPNUM {
// Coprocessor Instructions
0x1: decode OPCODE_4 {
0: decode OPCODE_4 {
0: decode CPNUM {
format FloatOp {
// Basic FPA Instructions
0: decode OPCODE_23_20 {
0x0: decode OPCODE_15 {
0: adf({{ Fd.sf = Fn.sf + Fm.sf; }});
1: mvf({{ Fd.sf = Fm.sf; }});
}
0x1: decode OPCODE_15 {
0: muf({{ Fd.sf = Fn.sf * Fm.sf; }});
1: mnf({{ Fd.sf = -Fm.sf; }});
}
0x2: decode OPCODE_15 {
0: suf({{ Fd.sf = Fn.sf - Fm.sf; }});
1: abs({{ Fd.sf = fabs(Fm.sf); }});
}
0x3: decode OPCODE_15 {
0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }});
1: rnd({{ Fd.sf = rint(Fm.sf); }});
}
0x4: decode OPCODE_15 {
0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }});
1: sqt({{ Fd.sf = sqrt(Fm.sf); }});
}
0x5: decode OPCODE_15 {
0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }});
1: log({{ Fd.sf = log10(Fm.sf); }});
}
0x6: decode OPCODE_15 {
0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }});
1: lgn({{ Fd.sf = log(Fm.sf); }});
}
0x7: decode OPCODE_15 {
0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }});
1: exp({{ Fd.sf = exp(Fm.sf); }});
}
0x8: decode OPCODE_15 {
0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }});
1: sin({{ Fd.sf = sin(Fm.sf); }});
}
0x9: decode OPCODE_15 {
0: fml({{ Fd.sf = Fn.sf * Fm.sf; }});
1: cos({{ Fd.sf = cos(Fm.sf); }});
}
0xa: decode OPCODE_15 {
0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }});
1: tan({{ Fd.sf = tan(Fm.sf); }});
}
0xb: decode OPCODE_15 {
0: frd({{ Fd.sf = Fm.sf / Fn.sf; }});
1: asn({{ Fd.sf = asin(Fm.sf); }});
}
0xc: decode OPCODE_15 {
0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }});
1: acs({{ Fd.sf = acos(Fm.sf); }});
}
0xd: decode OPCODE_15 {
1: atn({{ Fd.sf = atan(Fm.sf); }});
}
0xe: decode OPCODE_15 {
// Unnormalised Round
1: FailUnimpl::urd();
}
0xf: decode OPCODE_15 {
// Normalise
1: FailUnimpl::nrm();
}
}
1: decode OPCODE_15_12 {
0x1: decode OPCODE_23_20 {
0x0: decode OPCODE_15 {
0: adf({{ Fd.sf = Fn.sf + Fm.sf; }});
1: mvf({{ Fd.sf = Fm.sf; }});
}
0x1: decode OPCODE_15 {
0: muf({{ Fd.sf = Fn.sf * Fm.sf; }});
1: mnf({{ Fd.sf = -Fm.sf; }});
}
0x2: decode OPCODE_15 {
0: suf({{ Fd.sf = Fn.sf - Fm.sf; }});
1: abs({{ Fd.sf = fabs(Fm.sf); }});
}
0x3: decode OPCODE_15 {
0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }});
1: rnd({{ Fd.sf = rint(Fm.sf); }});
}
0x4: decode OPCODE_15 {
0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }});
1: sqt({{ Fd.sf = sqrt(Fm.sf); }});
}
0x5: decode OPCODE_15 {
0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }});
1: log({{ Fd.sf = log10(Fm.sf); }});
}
0x6: decode OPCODE_15 {
0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }});
1: lgn({{ Fd.sf = log(Fm.sf); }});
}
0x7: decode OPCODE_15 {
0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }});
1: exp({{ Fd.sf = exp(Fm.sf); }});
}
0x8: decode OPCODE_15 {
0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }});
1: sin({{ Fd.sf = sin(Fm.sf); }});
}
0x9: decode OPCODE_15 {
0: fml({{ Fd.sf = Fn.sf * Fm.sf; }});
1: cos({{ Fd.sf = cos(Fm.sf); }});
}
0xa: decode OPCODE_15 {
0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }});
1: tan({{ Fd.sf = tan(Fm.sf); }});
}
0xb: decode OPCODE_15 {
0: frd({{ Fd.sf = Fm.sf / Fn.sf; }});
1: asn({{ Fd.sf = asin(Fm.sf); }});
}
0xc: decode OPCODE_15 {
0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }});
1: acs({{ Fd.sf = acos(Fm.sf); }});
}
0xd: decode OPCODE_15 {
1: atn({{ Fd.sf = atan(Fm.sf); }});
}
0xe: decode OPCODE_15 {
// Unnormalised Round
1: FailUnimpl::urd();
}
0xf: decode OPCODE_15 {
// Normalise
1: FailUnimpl::nrm();
}
} // OPCODE_23_20
} // format FloatOp
} // CPNUM
1: decode CPNUM { // 27-24=1110,4 ==1
1: decode OPCODE_15_12 {
format FloatOp {
0xf: decode OPCODE_23_21 {
format FloatCmp {
0x4: cmf({{ Fn.df }}, {{ Fm.df }});
@ -417,36 +477,86 @@ format DataOp {
0x4: FailUnimpl::wfc();
0x5: FailUnimpl::rfc();
}
}
} // format FloatOp
}
}
0xa: decode MISC_OPCODE {
0x1: decode MEDIA_OPCODE {
0xf: decode RN {
0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }});
0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }});
0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }});
0xa: decode MISC_OPCODE {
0x1: decode MEDIA_OPCODE {
0xf: decode RN {
0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }});
0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }});
0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }});
}
0xe: decode RN {
0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }});
0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }});
0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }});
}
} // MEDIA_OPCODE (MISC_OPCODE 0x1)
} // MISC_OPCODE (CPNUM 0xA)
0xf: decode RN {
// Barrriers, Cache Maintence, NOPS
7: decode OPCODE_23_21 {
0: decode RM {
0: decode OPC2 {
4: decode OPCODE_20 {
0: PredOp::mcr_cp15_nop1({{ }}); // was wfi
}
}
1: WarnUnimpl::cp15_cache_maint();
4: WarnUnimpl::cp15_par();
5: decode OPC2 {
0,1: WarnUnimpl::cp15_cache_maint2();
4: PredOp::cp15_isb({{ ; }}, IsMemBarrier, IsSerializeBefore);
6,7: WarnUnimpl::cp15_bp_maint();
}
6: WarnUnimpl::cp15_cache_maint3();
8: WarnUnimpl::cp15_va_to_pa();
10: decode OPC2 {
1,2: WarnUnimpl::cp15_cache_maint3();
4: PredOp::cp15_dsb({{ ; }}, IsMemBarrier, IsSerializeBefore);
5: PredOp::cp15_dmb({{ ; }}, IsMemBarrier, IsSerializeBefore);
}
11: WarnUnimpl::cp15_cache_maint4();
13: decode OPC2 {
1: decode OPCODE_20 {
0: PredOp::mcr_cp15_nop2({{ }}); // was prefetch
}
}
14: WarnUnimpl::cp15_cache_maint5();
} // RM
} // OPCODE_23_21 CR
// Thread ID and context ID registers
// Thread ID register needs cheaper access than miscreg
13: WarnUnimpl::mcr_mrc_cp15_c7();
// All the rest
default: decode OPCODE_20 {
0: PredOp::mcr_cp15({{
fault = setCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2);
}});
1: PredOp::mrc_cp15({{
fault = readCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2);
}});
}
0xe: decode RN {
0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }});
0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }});
0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }});
}
}
} // RN
} // CPNUM (OP4 == 1)
} //OPCODE_4
#if FULL_SYSTEM
1: PredOp::swi({{ fault = new SupervisorCall; }}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
#else
1: PredOp::swi({{ if (testPredicate(CondCodes, condCode))
{
if (IMMED_23_0)
xc->syscall(IMMED_23_0);
else
xc->syscall(R7);
}
}
format PredOp {
// ARM System Call (SoftWare Interrupt)
1: swi({{ if (testPredicate(Cpsr, condCode))
{
if (IMMED_23_0)
xc->syscall(IMMED_23_0);
else
xc->syscall(R7);
}
}});
}
}
}});
#endif // FULL_SYSTEM
} // OPCODE_24
}
}

View file

@ -52,7 +52,7 @@ def format Branch(code,*opt_flags) {{
else:
inst_flags += ('IsCondControl', )
icode = 'if (testPredicate(Cpsr, condCode)) {\n'
icode = 'if (testPredicate(CondCodes, condCode)) {\n'
icode += code
icode += ' NPC = NPC + 4 + disp;\n'
icode += '} else {\n'
@ -90,7 +90,7 @@ def format BranchExchange(code,*opt_flags) {{
#Condition code
icode = 'if (testPredicate(Cpsr, condCode)) {\n'
icode = 'if (testPredicate(CondCodes, condCode)) {\n'
icode += code
icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n'
icode += '} else {\n'

View file

@ -119,8 +119,8 @@ let {{
_ic = %(fReg1)s >= %(fReg2)s;
_iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1;
Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
(Cpsr & 0x0FFFFFFF);
CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
(CondCodes & 0x0FFFFFFF);
'''
}};

View file

@ -72,6 +72,18 @@ let {{
'predicate_test': predicateTest},
['IsMicroop'])
microLdrRetUopCode = '''
Ra = Mem;
Cpsr = cpsrWriteByInstr(Cpsr, Spsr, 0xF, true);
'''
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
'MicroMemOp',
{'memacc_code': microLdrRetUopCode,
'ea_code':
'EA = Rb + (UP ? imm : -imm);',
'predicate_test': predicateTest},
['IsMicroop'])
microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
'MicroMemOp',
{'memacc_code': 'Mem = Ra;',
@ -80,14 +92,19 @@ let {{
['IsMicroop'])
header_output = MicroMemDeclare.subst(microLdrUopIop) + \
MicroMemDeclare.subst(microLdrRetUopIop) + \
MicroMemDeclare.subst(microStrUopIop)
decoder_output = MicroConstructor.subst(microLdrUopIop) + \
MicroConstructor.subst(microLdrRetUopIop) + \
MicroConstructor.subst(microStrUopIop)
exec_output = LoadExecute.subst(microLdrUopIop) + \
LoadExecute.subst(microLdrRetUopIop) + \
StoreExecute.subst(microStrUopIop) + \
LoadInitiateAcc.subst(microLdrUopIop) + \
LoadInitiateAcc.subst(microLdrRetUopIop) + \
StoreInitiateAcc.subst(microStrUopIop) + \
LoadCompleteAcc.subst(microLdrUopIop) + \
LoadCompleteAcc.subst(microLdrRetUopIop) + \
StoreCompleteAcc.subst(microStrUopIop)
}};
@ -178,73 +195,64 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
uint32_t regs_to_handle = reglist;
uint32_t start_addr = 0;
uint32_t regs = reglist;
uint32_t addr = 0;
bool up = machInst.puswl.up;
switch (puswl)
{
case 0x00: // stmda
case 0x01: // L ldmda_l
case 0x02: // W stmda_w
case 0x03: // WL ldmda_wl
start_addr = (ones << 2) - 4;
break;
case 0x08: // U stmia_u
case 0x09: // U L ldmia_ul
case 0x0a: // U W stmia
case 0x0b: // U WL ldmia
start_addr = 0;
break;
case 0x10: // P stmdb
case 0x11: // P L ldmdb
case 0x12: // P W stmdb
case 0x13: // P WL ldmdb
start_addr = (ones << 2); // U-bit is already 0 for subtract
break;
case 0x18: // PU stmib
case 0x19: // PU L ldmib
case 0x1a: // PU W stmib
case 0x1b: // PU WL ldmib
start_addr = 4;
break;
default:
panic("Unhandled Load/Store Multiple Instruction, "
"puswl = 0x%x", (unsigned) puswl);
break;
}
if (!up)
addr = (ones << 2) - 4;
// Add 0 to Rn and stick it in Raddr (register 17).
if (machInst.puswl.prepost)
addr += 4;
// Add 0 to Rn and stick it in ureg0.
// This is equivalent to a move.
microOps[0] = new MicroAddiUop(machInst, 17, RN, 0);
microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
unsigned j = 0;
for (int i = 1; i < ones+1; i++) {
// Get next available bit for transfer
while (! ( regs_to_handle & (1<<j)))
j++;
regs_to_handle &= ~(1<<j);
unsigned reg = 0;
bool force_user = machInst.puswl.psruser & !OPCODE_15;
bool exception_ret = machInst.puswl.psruser & OPCODE_15;
if (loadop)
microOps[i] = new MicroLdrUop(machInst, j, 17, start_addr);
else
microOps[i] = new MicroStrUop(machInst, j, 17, start_addr);
for (int i = 1; i < ones + 1; i++) {
// Find the next register.
while (!bits(regs, reg))
reg++;
replaceBits(regs, reg, 0);
unsigned regIdx = reg;
if (force_user) {
regIdx = intRegForceUser(regIdx);
}
if (machInst.puswl.loadOp) {
if (reg == INTREG_PC && exception_ret) {
// This must be the exception return form of ldm.
microOps[i] =
new MicroLdrRetUop(machInst, regIdx, INTREG_UREG0, addr);
} else {
microOps[i] =
new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr);
}
} else {
microOps[i] =
new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr);
}
if (up)
start_addr += 4;
addr += 4;
else
start_addr -= 4;
addr -= 4;
}
if (writeback) {
StaticInstPtr &lastUop = microOps[numMicroops - 1];
if (machInst.puswl.writeback) {
if (up) {
microOps[numMicroops-1] =
new MicroAddiUop(machInst, RN, RN, ones * 4);
lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
} else {
microOps[numMicroops-1] =
new MicroSubiUop(machInst, RN, RN, ones * 4);
lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
}
}
microOps[numMicroops-1]->setLastMicroop();
lastUop->setLastMicroop();
}
}};
@ -285,14 +293,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
if (writeback)
{
if (up) {
microOps[numMicroops-1] =
microOps[numMicroops - 1] =
new MicroAddiUop(machInst, RN, RN, disp8);
} else {
microOps[numMicroops-1] =
microOps[numMicroops - 1] =
new MicroSubiUop(machInst, RN, RN, disp8);
}
}
microOps[numMicroops-1]->setLastMicroop();
microOps[numMicroops - 1]->setLastMicroop();
}
}};
@ -316,14 +324,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
if (writeback) {
if (up) {
microOps[numMicroops-1] =
microOps[numMicroops - 1] =
new MicroAddiUop(machInst, RN, RN, disp8);
} else {
microOps[numMicroops-1] =
microOps[numMicroops - 1] =
new MicroSubiUop(machInst, RN, RN, disp8);
}
}
microOps[numMicroops-1]->setLastMicroop();
microOps[numMicroops - 1]->setLastMicroop();
}
}};

View file

@ -34,7 +34,7 @@
//
let {{
predicateTest = 'testPredicate(Cpsr, condCode)'
predicateTest = 'testPredicate(CondCodes, condCode)'
}};
def template PredOpExecute {{
@ -81,32 +81,45 @@ def template DataImmDecode {{
}};
let {{
calcCcCode = '''
if (%(canOverflow)s){
cprintf("canOverflow: %%d\\n", Rd < resTemp);
replaceBits(CondCodes, 27, Rd < resTemp);
} else {
uint16_t _ic, _iv, _iz, _in;
_in = (resTemp >> %(negBit)d) & 1;
_iz = (resTemp == 0);
_iv = %(ivValue)s & 1;
_ic = %(icValue)s & 1;
CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
(CondCodes & 0x0FFFFFFF);
calcCcCode = '''
uint16_t _ic, _iv, _iz, _in;
_in = (resTemp >> 31) & 1;
_iz = (resTemp == 0);
_iv = %(ivValue)s & 1;
_ic = %(icValue)s & 1;
Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
(Cpsr & 0x0FFFFFFF);
DPRINTF(Arm, "in = %%d\\n", _in);
DPRINTF(Arm, "iz = %%d\\n", _iz);
DPRINTF(Arm, "ic = %%d\\n", _ic);
DPRINTF(Arm, "iv = %%d\\n", _iv);
DPRINTF(Arm, "in = %%d\\n", _in);
DPRINTF(Arm, "iz = %%d\\n", _iz);
DPRINTF(Arm, "ic = %%d\\n", _ic);
DPRINTF(Arm, "iv = %%d\\n", _iv);
}
'''
}};
let {{
def getCcCode(flagtype):
icReg = icImm = iv = ''
negBit = 31
canOverflow = 'false'
if flagtype == "none":
icReg = icImm = 'Cpsr<29:>'
iv = 'Cpsr<28:>'
icReg = icImm = 'CondCodes<29:>'
iv = 'CondCodes<28:>'
elif flagtype == "llbit":
icReg = icImm = 'CondCodes<29:>'
iv = 'CondCodes<28:>'
negBit = 63
elif flagtype == "overflow":
canOverflow = "true"
icReg = icImm = iv = '0'
elif flagtype == "add":
icReg = icImm = 'findCarry(32, resTemp, Rn, op2)'
iv = 'findOverflow(32, resTemp, Rn, op2)'
@ -117,17 +130,32 @@ let {{
icReg = icImm = 'findCarry(32, resTemp, op2, ~Rn)'
iv = 'findOverflow(32, resTemp, op2, ~Rn)'
else:
icReg = 'shift_carry_rs(Rm, Rs, shift, Cpsr<29:>)'
icImm = 'shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>)'
iv = 'Cpsr<28:>'
return (calcCcCode % {"icValue" : icReg, "ivValue" : iv},
calcCcCode % {"icValue" : icImm, "ivValue" : iv})
icReg = 'shift_carry_rs(Rm, Rs<7:0>, shift, CondCodes<29:>)'
icImm = 'shift_carry_imm(Rm, shift_size, shift, CondCodes<29:>)'
iv = 'CondCodes<28:>'
return (calcCcCode % {"icValue" : icReg,
"ivValue" : iv,
"negBit" : negBit,
"canOverflow" : canOverflow },
calcCcCode % {"icValue" : icImm,
"ivValue" : iv,
"negBit" : negBit,
"canOverflow" : canOverflow })
def getImmCcCode(flagtype):
ivValue = icValue = ''
negBit = 31
canOverflow = 'false'
if flagtype == "none":
icValue = 'Cpsr<29:>'
ivValue = 'Cpsr<28:>'
icValue = 'CondCodes<29:>'
ivValue = 'CondCodes<28:>'
elif flagtype == "llbit":
icValue = 'CondCodes<29:>'
ivValue = 'CondCodes<28:>'
negBit = 63
elif flagtype == "overflow":
icVaule = ivValue = '0'
canOverflow = "true"
elif flagtype == "add":
icValue = 'findCarry(32, resTemp, Rn, rotated_imm)'
ivValue = 'findOverflow(32, resTemp, Rn, rotated_imm)'
@ -138,18 +166,18 @@ let {{
icValue = 'findCarry(32, resTemp, rotated_imm, ~Rn)'
ivValue = 'findOverflow(32, resTemp, rotated_imm, ~Rn)'
else:
icValue = '(rotate ? rotated_carry:Cpsr<29:>)'
ivValue = 'Cpsr<28:>'
icValue = '(rotate ? rotated_carry:CondCodes<29:>)'
ivValue = 'CondCodes<28:>'
return calcCcCode % vars()
}};
def format DataOp(code, flagtype = logic) {{
(regCcCode, immCcCode) = getCcCode(flagtype)
regCode = '''uint32_t op2 = shift_rm_rs(Rm, Rs,
shift, Cpsr<29:0>);
regCode = '''uint32_t op2 = shift_rm_rs(Rm, Rs<7:0>,
shift, CondCodes<29:>);
op2 = op2;''' + code
immCode = '''uint32_t op2 = shift_rm_imm(Rm, shift_size,
shift, Cpsr<29:0>);
shift, CondCodes<29:>);
op2 = op2;''' + code
regIop = InstObjParams(name, Name, 'PredIntOp',
{"code": regCode,

View file

@ -115,7 +115,7 @@ output exec {{
panic("attempt to execute unimplemented instruction '%s' "
"(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
inst2string(machInst));
return new UnimplementedOpcodeFault;
return new UnimpFault("Unimplemented Instruction");
}
Fault

View file

@ -74,7 +74,7 @@ output exec {{
{
panic("attempt to execute unknown instruction "
"(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst));
return new UnimplementedOpcodeFault;
return new UnimpFault("Unimplemented Instruction");
}
}};

View file

@ -33,8 +33,10 @@ let {{
# Generic substitutions for Arm instructions
def ArmGenericCodeSubs(code):
# Substitute in the shifted portion of operations
new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, Cpsr<29:>)', code)
new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code)
new_code = re.sub(r'Rm_Imm',
'shift_rm_imm(Rm, shift_size, shift, CondCodes<29:>)', code)
new_code = re.sub(r'Rm_Rs',
'shift_rm_rs(Rm, Rs, shift, CondCodes<29:>)', new_code)
return new_code
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,

View file

@ -58,15 +58,16 @@ def operands {{
'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite),
'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite),
'R7': ('IntReg', 'uw', '7', 'IsInteger', 5),
'R0': ('IntReg', 'uw', '0', 'IsInteger', 0),
#Destination register for load/store double instructions
'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite),
'Rde': ('IntReg', 'uw', '(RD | 1)', 'IsInteger', 5, maybePCRead, maybePCWrite),
'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 6),
'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 7),
'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 8),
'LR': ('IntReg', 'uw', '14', 'IsInteger', 9),
'Rhi': ('IntReg', 'uw', 'INTREG_RHI', 'IsInteger', 7),
'Rlo': ('IntReg', 'uw', 'INTREG_RLO', 'IsInteger', 8),
'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 9),
'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', 'IsInteger', 10),
#Register fields for microops
'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 11, maybePCRead, maybePCWrite),
@ -80,12 +81,13 @@ def operands {{
#Memory Operand
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 30),
'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', 'IsInteger', 40),
'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', 'IsInteger', 41),
'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', 'IsInteger', 42),
'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', 'IsInteger', 43),
'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', 'IsInteger', 44),
'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 45),
'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 46)
'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 40),
'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', (None, None, 'IsControl'), 41),
'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', (None, None, 'IsControl'), 42),
'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', (None, None, 'IsControl'), 43),
'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', (None, None, 'IsControl'), 44),
'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', (None, None, 'IsControl'), 45),
'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 50),
'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 51)
}};

View file

@ -104,6 +104,8 @@ namespace ArmISA
const int WordBytes = 4;
const int HalfwordBytes = 2;
const int ByteBytes = 1;
const uint32_t HighVecs = 0xFFFF0000;
};
using namespace ArmISA;

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* 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
@ -25,43 +24,34 @@
* 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
*/
/*
* TypeAST.C
*
* Description: See TypeAST.hh
*
* $Id: TypeAST.C,v 3.1 2003/03/22 15:15:16 xu Exp $
*
*/
#ifndef __ARCH_ARM_KERNEL_STATS_HH__
#define __ARCH_ARM_KERNEL_STATS_HH__
#include "mem/slicc/ast/TypeAST.hh"
#include <map>
#include <stack>
#include <string>
#include <vector>
TypeAST::TypeAST(string* ident_ptr)
: AST()
#include "kern/kernel_stats.hh"
namespace ArmISA {
namespace Kernel {
enum cpu_mode { hypervisor, kernel, user, idle, cpu_mode_num };
extern const char *modestr[];
class Statistics : public ::Kernel::Statistics
{
m_ident_ptr = ident_ptr;
}
public:
Statistics(System *system) : ::Kernel::Statistics(system)
{}
};
TypeAST::~TypeAST()
{
delete m_ident_ptr;
} /* end namespace ArmISA::Kernel */
} /* end namespace ArmISA */
}
string TypeAST::toString() const
{
return *m_ident_ptr;
}
Type* TypeAST::lookupType() const
{
Type* type_ptr = g_sym_table.getType(*m_ident_ptr);
if (type_ptr != NULL) {
return type_ptr;
} else {
error("Type '" + *m_ident_ptr + "' not declared.");
}
return NULL; // Not reached
}
#endif // __ARCH_ARM_KERNEL_STATS_HH__

View file

@ -86,6 +86,7 @@ class ArmLinux : public Linux
static const unsigned TIOCISATTY_ = 0x2000745e;
static const unsigned TIOCGETS_ = 0x402c7413;
static const unsigned TIOCGETA_ = 0x40127417;
static const unsigned TCSETAW_ = 0x5407; // 2.6.15 kernel
//@}
/// For table().
@ -147,6 +148,21 @@ class ArmLinux : public Linux
uint64_t st_ino;
} tgt_stat64;
typedef struct {
int32_t uptime; /* Seconds since boot */
uint32_t loads[3]; /* 1, 5, and 15 minute load averages */
uint32_t totalram; /* Total usable main memory size */
uint32_t freeram; /* Available memory size */
uint32_t sharedram; /* Amount of shared memory */
uint32_t bufferram; /* Memory used by buffers */
uint32_t totalswap; /* Total swap space size */
uint32_t freeswap; /* swap space still available */
uint16_t procs; /* Number of current processes */
uint32_t totalhigh; /* Total high memory size */
uint32_t freehigh; /* Available high memory size */
uint32_t mem_unit; /* Memory unit size in bytes */
} tgt_sysinfo;
};

View file

@ -50,7 +50,8 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
int index = 0;
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
strcpy(name->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu");
@ -179,7 +180,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 113 */ SyscallDesc("vm86", unimplementedFunc),
/* 114 */ SyscallDesc("wait4", unimplementedFunc),
/* 115 */ SyscallDesc("swapoff", unimplementedFunc),
/* 116 */ SyscallDesc("sysinfo", unimplementedFunc),
/* 116 */ SyscallDesc("sysinfo", sysinfoFunc<ArmLinux>),
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
@ -417,7 +418,8 @@ static SyscallReturn
setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
uint32_t tlsPtr = process->getSyscallArg(tc, 0);
int index = 0;
uint32_t tlsPtr = process->getSyscallArg(tc, index);
tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0,
(uint8_t *)&tlsPtr, sizeof(tlsPtr));
@ -511,12 +513,12 @@ ArmLinuxProcess::startup()
}
ArmISA::IntReg
ArmLinuxProcess::getSyscallArg(ThreadContext *tc, int i)
ArmLinuxProcess::getSyscallArg(ThreadContext *tc, int &i)
{
// Linux apparently allows more parameter than the ABI says it should.
// This limit may need to be increased even further.
assert(i < 6);
return tc->readIntReg(ArgumentReg0 + i);
return tc->readIntReg(ArgumentReg0 + i++);
}
void

View file

@ -44,7 +44,7 @@ class ArmLinuxProcess : public ArmLiveProcess
void startup();
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int i);
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
void setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val);
/// The target system's hostname.

View file

@ -55,23 +55,24 @@ namespace ArmISA
enum MiscRegIndex {
MISCREG_CPSR = 0,
MISCREG_SPSR,
MISCREG_SPSR,
MISCREG_SPSR_FIQ,
MISCREG_SPSR_IRQ,
MISCREG_SPSR_SVC,
MISCREG_SPSR_MON,
MISCREG_SPSR_UND,
MISCREG_SPSR_ABT,
MISCREG_FPSR,
MISCREG_FPSID,
MISCREG_FPSCR,
MISCREG_FPEXC,
NUM_MISCREGS
MISCREG_SCTLR,
NUM_MISCREGS
};
const char * const miscRegName[NUM_MISCREGS] = {
"cpsr",
"spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und", "spsr_abt",
"fpsr"
"cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und",
"spsr_abt", "fpsr", "fpsid", "fpscr", "fpexc", "sctlr"
};
BitUnion32(CPSR)
@ -80,8 +81,10 @@ namespace ArmISA
Bitfield<29> c;
Bitfield<28> v;
Bitfield<27> q;
Bitfield<26,25> it1;
Bitfield<24> j;
Bitfield<19, 16> ge;
Bitfield<15,10> it2;
Bitfield<9> e;
Bitfield<8> a;
Bitfield<7> i;
@ -89,6 +92,35 @@ namespace ArmISA
Bitfield<5> t;
Bitfield<4, 0> mode;
EndBitUnion(CPSR)
// This mask selects bits of the CPSR that actually go in the CondCodes
// integer register to allow renaming.
static const uint32_t CondCodesMask = 0xF80F0000;
BitUnion32(SCTLR)
Bitfield<30> te; // Thumb Exception Enable
Bitfield<29> afe; // Access flag enable
Bitfield<28> tre; // TEX Remap bit
Bitfield<27> nmfi;// Non-maskable fast interrupts enable
Bitfield<25> ee; // Exception Endianness bit
Bitfield<24> ve; // Interrupt vectors enable
Bitfield<23> rao1;// Read as one
Bitfield<22> u; // Alignment (now unused)
Bitfield<21> fi; // Fast interrupts configuration enable
Bitfield<18> rao2;// Read as one
Bitfield<17> ha; // Hardware access flag enable
Bitfield<16> rao3;// Read as one
Bitfield<14> rr; // Round robin cache replacement
Bitfield<13> v; // Base address for exception vectors
Bitfield<12> i; // instruction cache enable
Bitfield<11> z; // branch prediction enable bit
Bitfield<10> sw; // Enable swp/swpb
Bitfield<6,3> rao4;// Read as one
Bitfield<7> b; // Endianness support (unused)
Bitfield<2> c; // Cache enable bit
Bitfield<1> a; // Alignment fault checking
Bitfield<0> m; // MMU enable bit
EndBitUnion(SCTLR)
};
#endif // __ARCH_ARM_MISCREGS_HH__

View file

@ -97,7 +97,8 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]);
//CPSR
newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR);
newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR) |
tc->readIntReg(INTREG_CONDCODES);
changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]);
}

View file

@ -324,10 +324,10 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
}
ArmISA::IntReg
ArmLiveProcess::getSyscallArg(ThreadContext *tc, int i)
ArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 4);
return tc->readIntReg(ArgumentReg0 + i);
return tc->readIntReg(ArgumentReg0 + i++);
}
void

View file

@ -53,7 +53,7 @@ class ArmLiveProcess : public LiveProcess
public:
void argsInit(int intSize, int pageSize);
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int i);
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
void setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};

View file

@ -32,6 +32,7 @@
#define __ARCH_ARM_REGISTERS_HH__
#include "arch/arm/max_inst_regs.hh"
#include "arch/arm/intregs.hh"
#include "arch/arm/miscregs.hh"
namespace ArmISA {
@ -51,13 +52,11 @@ typedef float FloatReg;
typedef uint64_t MiscReg;
// Constants Related to the number of registers
const int NumIntArchRegs = 16;
const int NumIntSpecialRegs = 19;
const int NumIntArchRegs = NUM_ARCH_INTREGS;
const int NumFloatArchRegs = 16;
const int NumFloatSpecialRegs = 5;
const int NumInternalProcRegs = 0;
const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs;
const int NumIntRegs = NUM_INTREGS;
const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;
const int NumMiscRegs = NUM_MISCREGS;
@ -72,12 +71,11 @@ const int ArgumentReg1 = 1;
const int ArgumentReg2 = 2;
const int ArgumentReg3 = 3;
const int FramePointerReg = 11;
const int StackPointerReg = 13;
const int ReturnAddressReg = 14;
const int PCReg = 15;
const int StackPointerReg = INTREG_SP;
const int ReturnAddressReg = INTREG_LR;
const int PCReg = INTREG_PC;
const int ZeroReg = NumIntArchRegs;
const int AddrReg = ZeroReg + 1; // Used to generate address for uops
const int ZeroReg = INTREG_ZERO;
const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ReturnValueReg;
@ -116,35 +114,6 @@ enum FCSRFields {
Cause_Field = 11
};
enum MiscIntRegNums {
zero_reg = NumIntArchRegs,
addr_reg,
rhi,
rlo,
r8_fiq, /* FIQ mode register bank */
r9_fiq,
r10_fiq,
r11_fiq,
r12_fiq,
r13_fiq, /* FIQ mode SP and LR */
r14_fiq,
r13_irq, /* IRQ mode SP and LR */
r14_irq,
r13_svc, /* SVC mode SP and LR */
r14_svc,
r13_undef, /* UNDEF mode SP and LR */
r14_undef,
r13_abt, /* ABT mode SP and LR */
r14_abt
};
} // namespace ArmISA
#endif

151
src/arch/arm/stacktrace.cc Normal file
View file

@ -0,0 +1,151 @@
/*
* 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 <string>
#include "arch/arm/isa_traits.hh"
#include "arch/arm/stacktrace.hh"
#include "arch/arm/vtophys.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "sim/system.hh"
using namespace std;
namespace ArmISA
{
ProcessInfo::ProcessInfo(ThreadContext *_tc)
: tc(_tc)
{
Addr addr = 0;
VirtualPort *vp;
vp = tc->getVirtPort();
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
panic("thread info not compiled into kernel\n");
thread_info_size = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
panic("thread info not compiled into kernel\n");
task_struct_size = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
panic("thread info not compiled into kernel\n");
task_off = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
panic("thread info not compiled into kernel\n");
pid_off = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n");
name_off = vp->readGtoH<int32_t>(addr);
}
Addr
ProcessInfo::task(Addr ksp) const
{
return 0;
}
int
ProcessInfo::pid(Addr ksp) const
{
return -1;
}
string
ProcessInfo::name(Addr ksp) const
{
return "Implement me";
}
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)
{
}
bool
StackTrace::isEntry(Addr addr)
{
return false;
}
bool
StackTrace::decodeStack(MachInst inst, int &disp)
{
return false;
}
bool
StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
{
return false;
}
/*
* 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)
{
return false;
}
#if TRACING_ON
void
StackTrace::dump()
{
DPRINTFN("------ Stack ------\n");
DPRINTFN(" Not implemented\n");
}
#endif
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 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
@ -26,8 +25,7 @@
* (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
* Stephen Hines
* Authors: Nathan Binkert
*/
#ifndef __ARCH_ARM_STACKTRACE_HH__
@ -37,11 +35,11 @@
#include "cpu/static_inst.hh"
class ThreadContext;
class StackTrace;
namespace ArmISA
{
class StackTrace;
class ProcessInfo
{
private:
@ -64,7 +62,7 @@ class ProcessInfo
class StackTrace
{
protected:
typedef TheISA::MachInst MachInst;
typedef ArmISA::MachInst MachInst;
private:
ThreadContext *tc;
std::vector<Addr> stack;
@ -94,10 +92,6 @@ class StackTrace
public:
const std::vector<Addr> &getstack() const { return stack; }
static const int user = 1;
static const int console = 2;
static const int unknown = 3;
#if TRACING_ON
private:
void dump();
@ -123,6 +117,6 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
return true;
}
}
} // Namespace ArmISA
#endif // __ARCH_ARM_STACKTRACE_HH__

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2002-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,20 +24,28 @@
* 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
*/
/*
* TypeFieldAST.C
*
* Description: See TypeFieldAST.hh
*
* $Id$
*
*/
#include "arch/arm/system.hh"
#include "mem/slicc/ast/TypeFieldAST.hh"
TypeFieldAST::TypeFieldAST(PairListAST* pairs_ptr)
: AST(pairs_ptr->getPairs()) {
using namespace LittleEndianGuest;
ArmSystem::ArmSystem(Params *p)
: System(p)
{
}
ArmSystem::~ArmSystem()
{
}
ArmSystem *
ArmSystemParams::create()
{
return new ArmSystem(this);
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* 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
@ -25,36 +24,33 @@
* 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
*/
/*
* StatementAST.C
*
* Description: See StatementAST.hh
*
* $Id$
*
*/
#ifndef __ARCH_ARM_SYSTEM_HH__
#define __ARCH_ARM_SYSTEM_HH__
#include "mem/slicc/ast/StatementAST.hh"
#include <string>
#include <vector>
static int indentation_depth = 1;
#include "params/ArmSystem.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"
void inc_indent()
class ArmSystem : public System
{
indentation_depth++;
}
public:
typedef ArmSystemParams Params;
ArmSystem(Params *p);
~ArmSystem();
virtual Addr fixFuncEventAddr(Addr addr)
{
//XXX This may eventually have to do something useful.
return addr;
}
};
void dec_indent()
{
indentation_depth--;
}
#endif
string indent_str()
{
string temp;
for(int i=0; i<indentation_depth; i++) {
temp += " ";
}
return temp;
}

View file

@ -287,7 +287,15 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
return NoFault;
#else
fatal("translate atomic not yet implemented\n");
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
if (!sctlr.m) {
req->setPaddr(req->getVaddr());
return NoFault;
}
panic("MMU translation not implemented\n");
return NoFault;
#endif
}

View file

@ -45,16 +45,20 @@ namespace ArmISA
// All the different types of opcode fields.
Bitfield<27, 25> encoding;
Bitfield<25> useImm;
Bitfield<24, 21> opcode;
Bitfield<24, 20> mediaOpcode;
Bitfield<24> opcode24;
Bitfield<23, 20> opcode23_20;
Bitfield<23, 21> opcode23_21;
Bitfield<20> opcode20;
Bitfield<22> opcode22;
Bitfield<19> opcode19;
Bitfield<18> opcode18;
Bitfield<15, 12> opcode15_12;
Bitfield<15> opcode15;
Bitfield<7, 4> miscOpcode;
Bitfield<7,5> opc2;
Bitfield<7> opcode7;
Bitfield<4> opcode4;
@ -156,6 +160,7 @@ namespace ArmISA
MODE_FIQ = 17,
MODE_IRQ = 18,
MODE_SVC = 19,
MODE_MON = 22,
MODE_ABORT = 23,
MODE_UNDEFINED = 27,
MODE_SYSTEM = 31

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 ARM Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,49 +24,53 @@
* 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
*/
/*
* ExprStatementAST.C
*
* Description: See ExprStatementAST.hh
*
* $Id$
*
*/
#include "mem/slicc/ast/ExprStatementAST.hh"
#include "arch/arm/faults.hh"
#include "arch/arm/utility.hh"
#include "cpu/thread_context.hh"
ExprStatementAST::ExprStatementAST(ExprAST* expr_ptr)
: StatementAST()
namespace ArmISA {
void
initCPU(ThreadContext *tc, int cpuId)
{
m_expr_ptr = expr_ptr;
// Reset CP15?? What does that mean -- ali
// FPEXC.EN = 0
static Fault reset = new Reset;
if (cpuId == 0)
reset->invoke(tc);
}
ExprStatementAST::~ExprStatementAST()
{
delete m_expr_ptr;
uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
#if FULL_SYSTEM
panic("getArgument() not implemented for ARM!\n");
#else
panic("getArgument() only implemented for FULL_SYSTEM\n");
M5_DUMMY_RETURN
#endif
}
void ExprStatementAST::generate(string& code, Type* return_type_ptr) const
Fault
setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2)
{
code += indent_str();
Type* actual_type_ptr = m_expr_ptr->generate(code);
code += ";\n";
// The return type must be void
Type* expected_type_ptr = g_sym_table.getType("void");
if (expected_type_ptr != actual_type_ptr) {
m_expr_ptr->error("Non-void return must not be ignored, return type is '" + actual_type_ptr->toString() + "'");
}
return new UnimpFault(csprintf("MCR CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n",
CRn, opc1, CRm, opc2));
}
void ExprStatementAST::findResources(Map<Var*, string>& resource_list) const
Fault
readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2)
{
m_expr_ptr->findResources(resource_list);
return new UnimpFault(csprintf("MRC CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n",
CRn, opc1, CRm, opc2));
}
void ExprStatementAST::print(ostream& out) const
{
out << "[ExprStatementAST: " << *m_expr_ptr << "]";
}

View file

@ -125,6 +125,20 @@ namespace ArmISA {
{
panic("Copy Misc. Regs Not Implemented Yet\n");
}
void initCPU(ThreadContext *tc, int cpuId);
static inline bool
inUserMode(ThreadContext *tc)
{
return (tc->readMiscRegNoEffect(MISCREG_CPSR) & 0x1f) == MODE_USER;
}
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
Fault setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
};

File diff suppressed because it is too large Load diff

View file

@ -34,10 +34,6 @@ import traceback
# get type names
from types import *
# Prepend the directory where the PLY lex & yacc modules are found
# to the search path.
sys.path[0:0] = [os.environ['M5_PLY']]
from ply import lex
from ply import yacc

View file

@ -28,10 +28,11 @@
#
# Authors: Jaidev Patwardhan
from m5 import build_env
from m5.defines import buildEnv
from System import *
if build_env['FULL_SYSTEM']:
if buildEnv['FULL_SYSTEM']:
class BareIronMipsSystem(MipsSystem):
type = 'BareIronMipsSystem'
system_type = 34

View file

@ -29,12 +29,13 @@
# Authors: Jaidev Patwardhan
# Korey Sewell
from m5.SimObject import SimObject
from m5.defines import buildEnv
from m5.params import *
from BaseCPU import BaseCPU
class BaseMipsCPU(BaseCPU)
if build_env['TARGET_ISA'] == 'mips':
if buildEnv['TARGET_ISA'] == 'mips':
CP0_IntCtl_IPTI = Param.Unsigned(0,"No Description")
CP0_IntCtl_IPPCI = Param.Unsigned(0,"No Description")
CP0_SrsCtl_HSS = Param.Unsigned(0,"No Description")

View file

@ -28,10 +28,10 @@
#
# Authors: Jaidev Patwardhan
from m5.SimObject import SimObject
from m5.defines import buildEnv
from m5.params import *
from m5.proxy import *
from m5 import build_env
from System import System
class MipsSystem(System):
@ -42,7 +42,7 @@ class MipsSystem(System):
system_type = Param.UInt64("Type of system we are emulating")
system_rev = Param.UInt64("Revision of system we are emulating")
if build_env['FULL_SYSTEM']:
if buildEnv['FULL_SYSTEM']:
class LinuxMipsSystem(MipsSystem):
type = 'LinuxMipsSystem'
system_type = 34

View file

@ -463,6 +463,8 @@ MipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl)
uint64_t b_values[SIMD_MAX_VALS];
uint64_t c_values[SIMD_MAX_VALS];
memset(c_values, 0, sizeof(c_values));
simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
@ -743,7 +745,7 @@ MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
int nvals = SIMD_NVALS[fmt];
uint64_t a_values[SIMD_MAX_VALS];
uint64_t b_values[SIMD_MAX_VALS];
int64_t temp[2];
int64_t temp[2] = {0, 0};
uint32_t ouflag = 0;
simdUnpack(a, a_values, fmt, SIGNED);

View file

@ -172,8 +172,11 @@ namespace MipsISA
return reg;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
void serialize(EventManager *em, std::ostream &os)
{}
void unserialize(EventManager *em, Checkpoint *cp,
const std::string &section)
{}
};
}

View file

@ -619,7 +619,7 @@ def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3;
def format Prefetch(ea_code = {{ EA = Rs + disp; }},
mem_flags = [], pf_flags = [], inst_flags = []) {{
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
'IsDataPrefetch', 'MemReadOp']

View file

@ -100,6 +100,7 @@ class MipsLinux : public Linux
static const unsigned TIOCISATTY_ = 0x5480;
static const unsigned TIOCGETS_ = 0x540d;
static const unsigned TIOCGETA_ = 0x7417;
static const unsigned TCSETAW_ = 0x5403; // 2.6.15 kernel
//@}
/// For table().
@ -126,6 +127,22 @@ class MipsLinux : public Linux
/// assign themselves to process IDs reserved for
/// the root users.
static const int NUM_ROOT_PROCS = 2;
typedef struct {
int32_t uptime; /* Seconds since boot */
uint32_t loads[3]; /* 1, 5, and 15 minute load averages */
uint32_t totalram; /* Total usable main memory size */
uint32_t freeram; /* Available memory size */
uint32_t sharedram; /* Amount of shared memory */
uint32_t bufferram; /* Memory used by buffers */
uint32_t totalswap; /* Total swap space size */
uint32_t freeswap; /* swap space still available */
uint16_t procs; /* Number of current processes */
uint32_t totalhigh; /* Total high memory size */
uint32_t freehigh; /* Available high memory size */
uint32_t mem_unit; /* Memory unit size in bytes */
} tgt_sysinfo;
};
#endif

View file

@ -51,7 +51,8 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
int index = 0;
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
strcpy(name->sysname, "Linux");
strcpy(name->nodename,"m5.eecs.umich.edu");
@ -70,14 +71,16 @@ static SyscallReturn
sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = process->getSyscallArg(tc, 0);
// unsigned nbytes = process->getSyscallArg(tc, 2);
int index = 0;
unsigned op = process->getSyscallArg(tc, index);
unsigned bufPtr = process->getSyscallArg(tc, index);
// unsigned nbytes = process->getSyscallArg(tc, index);
switch (op) {
case 45:
{
// GSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> fpcr(bufPtr);
// I don't think this exactly matches the HW FPCR
*fpcr = 0;
fpcr.copyOut(tc->getMemPort());
@ -97,15 +100,17 @@ static SyscallReturn
sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = process->getSyscallArg(tc, 0);
// unsigned nbytes = process->getSyscallArg(tc, 2);
int index = 0;
unsigned op = process->getSyscallArg(tc, index);
Addr bufPtr = process->getSyscallArg(tc, index);
// unsigned nbytes = process->getSyscallArg(tc, index);
switch (op) {
case 14:
{
// SSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
TypedBufferArg<uint64_t> fpcr(bufPtr);
// I don't think this exactly matches the HW FPCR
fpcr.copyIn(tc->getMemPort());
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
@ -238,7 +243,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 113 */ SyscallDesc("vm86", unimplementedFunc),
/* 114 */ SyscallDesc("wait4", unimplementedFunc),
/* 115 */ SyscallDesc("swapoff", unimplementedFunc),
/* 116 */ SyscallDesc("sysinfo", unimplementedFunc),
/* 116 */ SyscallDesc("sysinfo", sysinfoFunc<MipsLinux>),
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
@ -413,12 +418,6 @@ MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{ }
void
MipsLinuxProcess::startup()
{
MipsLiveProcess::argsInit(MachineBytes, VMPageSize);
}
SyscallDesc*
MipsLinuxProcess::getDesc(int callnum)
{

View file

@ -43,8 +43,6 @@ class MipsLinuxProcess : public MipsLiveProcess
/// Constructor.
MipsLinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
void startup();
virtual SyscallDesc* getDesc(int callnum);
/// The target system's hostname.

View file

@ -32,9 +32,15 @@
#include "arch/mips/isa_traits.hh"
#include "arch/mips/process.hh"
#include "base/loader/object_file.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/system.hh"
using namespace std;
@ -62,14 +68,89 @@ MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params,
void
MipsLiveProcess::startup()
{
Process::startup();
argsInit(MachineBytes, VMPageSize);
}
void
MipsLiveProcess::argsInit(int intSize, int pageSize)
{
// load object file into target memory
objFile->loadSections(initVirtMem);
// Calculate how much space we need for arg & env arrays.
int argv_array_size = intSize * (argv.size() + 1);
int envp_array_size = intSize * (envp.size() + 1);
int arg_data_size = 0;
for (vector<string>::size_type i = 0; i < argv.size(); ++i) {
arg_data_size += argv[i].size() + 1;
}
int env_data_size = 0;
for (vector<string>::size_type i = 0; i < envp.size(); ++i) {
env_data_size += envp[i].size() + 1;
}
int space_needed =
argv_array_size + envp_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
pTable->allocate(stack_min, roundUp(stack_size, pageSize));
// map out initial stack contents
// ========
// NOTE: Using uint32_t hardcodes MIPS32 and not MIPS64
// even if MIPS64 was intended. This is because the
// copyStringArray function templates on the parameters.
// Elegant way to check intSize and vary between 32/64?
// ========
uint32_t argv_array_base = stack_min + intSize; // room for argc
uint32_t envp_array_base = argv_array_base + argv_array_size;
uint32_t arg_data_base = envp_array_base + envp_array_size;
uint32_t env_data_base = arg_data_base + arg_data_size;
// write contents to stack
uint32_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);
ThreadContext *tc = system->getThreadContext(contextIds[0]);
setSyscallArg(tc, 0, argc);
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
tc->setPC(prog_entry);
tc->setNextPC(prog_entry + sizeof(MachInst));
tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
}
MipsISA::IntReg
MipsLiveProcess::getSyscallArg(ThreadContext *tc, int i)
MipsLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i);
return tc->readIntReg(FirstArgumentReg + i++);
}
void

View file

@ -45,10 +45,12 @@ class MipsLiveProcess : public LiveProcess
protected:
MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
virtual void startup();
void startup();
void argsInit(int intSize, int pageSize);
public:
MipsISA::IntReg getSyscallArg(ThreadContext *tc, int i);
MipsISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
void setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};

View file

@ -0,0 +1,37 @@
# -*- mode:python -*-
# Copyright (c) 2009 The University of Edinburgh
# 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: Timothy M. Jones
from m5.SimObject import SimObject
from m5.params import *
class PowerTLB(SimObject):
type = 'PowerTLB'
cxx_class = 'PowerISA::TLB'
size = Param.Int(64, "TLB size")

61
src/arch/power/SConscript Normal file
View file

@ -0,0 +1,61 @@
# -*- mode:python -*-
# Copyright (c) 2009 The University of Edinburgh
# 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: Timothy M. Jones
Import('*')
if env['TARGET_ISA'] == 'power':
# Workaround for bug in SCons version > 0.97d20071212
# Scons bug id: 2006 M5 Bug id: 308
Dir('isa/formats')
Source('insts/branch.cc')
Source('insts/mem.cc')
Source('insts/integer.cc')
Source('insts/floating.cc')
Source('insts/condition.cc')
Source('insts/static_inst.cc')
Source('pagetable.cc')
Source('tlb.cc')
SimObject('PowerTLB.py')
TraceFlag('Power')
if not env['FULL_SYSTEM']:
Source('process.cc')
Source('linux/linux.cc')
Source('linux/process.cc')
# 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)

33
src/arch/power/SConsopts Normal file
View file

@ -0,0 +1,33 @@
# -*- mode:python -*-
# Copyright (c) 2009 The University of Edinburgh
# 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: Timothy M. Jones
Import('*')
all_isa_list.append('power')

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,48 +25,63 @@
* 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.
*/
/*
* $Id$
*
* Authors: Gabe Black
* Timothy M. Jones
*/
#include "mem/slicc/symbols/Symbol.hh"
#ifndef __ARCH_POWER_FAULTS_HH__
#define __ARCH_POWER_FAULTS_HH__
Symbol::Symbol(string id, const Location& location, const Map<string, string>& pairs)
#include "sim/faults.hh"
namespace PowerISA
{
m_id = id;
m_location = location;
m_pairs = pairs;
if (!existPair("short")) {
addPair("short", m_id);
}
m_used = false;
class PowerFault : public FaultBase
{
protected:
FaultName _name;
PowerFault(FaultName name)
: _name(name)
{
}
FaultName
name() const
{
return _name;
}
};
class UnimplementedOpcodeFault : public PowerFault
{
public:
UnimplementedOpcodeFault()
: PowerFault("Unimplemented Opcode")
{
}
};
class MachineCheckFault : public PowerFault
{
public:
MachineCheckFault()
: PowerFault("Machine Check")
{
}
};
static inline Fault
genMachineCheckFault()
{
return new MachineCheckFault();
}
Symbol::Symbol(string id, const Location& location)
{
m_id = id;
m_location = location;
if (!existPair("short")) {
addPair("short", m_id);
}
m_used = false;
}
} // PowerISA namespace
const string& Symbol::lookupPair(const string& key) const
{
if (!existPair(key)) {
error("Value for pair '" + key + "' missing.");
}
return m_pairs.lookup(key);
}
void Symbol::addPair(const string& key, const string& value)
{
if (existPair(key)) {
warning("Pair key '" + key + "' re-defined. new: '" + value + "' old: '" + lookupPair(key) + "'");
}
m_pairs.add(key, value);
}
#endif // __ARCH_POWER_FAULTS_HH__

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#include "arch/power/insts/branch.hh"
#include "base/loader/symtab.hh"
using namespace PowerISA;
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;
}
Addr
BranchPCRel::branchTarget(Addr pc) const
{
return (uint32_t)(pc + disp);
}
std::string
BranchPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
Addr target = pc + disp;
std::string str;
if (symtab && symtab->findSymbol(target, str))
ss << str;
else
ccprintf(ss, "0x%x", target);
return ss.str();
}
Addr
BranchNonPCRel::branchTarget(Addr pc) const
{
return targetAddr;
}
std::string
BranchNonPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
std::string str;
if (symtab && symtab->findSymbol(targetAddr, str))
ss << str;
else
ccprintf(ss, "0x%x", targetAddr);
return ss.str();
}
Addr
BranchPCRelCond::branchTarget(Addr pc) const
{
return (uint32_t)(pc + disp);
}
std::string
BranchPCRelCond::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
ss << bo << ", " << bi << ", ";
Addr target = pc + disp;
std::string str;
if (symtab && symtab->findSymbol(target, str))
ss << str;
else
ccprintf(ss, "0x%x", target);
return ss.str();
}
Addr
BranchNonPCRelCond::branchTarget(Addr pc) const
{
return targetAddr;
}
std::string
BranchNonPCRelCond::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
ss << bo << ", " << bi << ", ";
std::string str;
if (symtab && symtab->findSymbol(targetAddr, str))
ss << str;
else
ccprintf(ss, "0x%x", targetAddr);
return ss.str();
}
Addr
BranchRegCond::branchTarget(ThreadContext *tc) const
{
uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1]);
return (regVal & 0xfffffffc);
}
std::string
BranchRegCond::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
ss << bo << ", " << bi << ", ";
return ss.str();
}

View file

@ -0,0 +1,241 @@
/* Copyright (c) 2007-2008 The Florida State University
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#ifndef __ARCH_POWER_INSTS_BRANCH_HH__
#define __ARCH_POWER_INSTS_BRANCH_HH__
#include "arch/power/insts/static_inst.hh"
namespace PowerISA
{
/**
* 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 PowerStaticInst
{
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)
: PowerStaticInst(mnem, _machInst, __opClass),
cachedPC(0), cachedSymtab(0)
{
}
const std::string &
disassemble(Addr pc, const SymbolTable *symtab) const;
};
/**
* Base class for unconditional, PC-relative branches.
*/
class BranchPCRel : public PCDependentDisassembly
{
protected:
/// Displacement
uint32_t disp;
/// Constructor.
BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
: PCDependentDisassembly(mnem, _machInst, __opClass),
disp(machInst.li << 2)
{
// If bit 26 is 1 then sign extend
if (disp & 0x2000000) {
disp |= 0xfc000000;
}
}
Addr branchTarget(Addr pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Base class for unconditional, non PC-relative branches.
*/
class BranchNonPCRel : public PCDependentDisassembly
{
protected:
/// Target address
uint32_t targetAddr;
/// Constructor.
BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
: PCDependentDisassembly(mnem, _machInst, __opClass),
targetAddr(machInst.li << 2)
{
// If bit 26 is 1 then sign extend
if (targetAddr & 0x2000000) {
targetAddr |= 0xfc000000;
}
}
Addr branchTarget(Addr pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Base class for conditional branches.
*/
class BranchCond : public PCDependentDisassembly
{
protected:
/// Fields needed for conditions
uint32_t bo;
uint32_t bi;
/// Constructor.
BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass)
: PCDependentDisassembly(mnem, _machInst, __opClass),
bo(machInst.bo),
bi(machInst.bi)
{
}
inline bool
ctrOk(uint32_t& ctr) const
{
bool ctr_ok;
if (bo & 4) {
ctr_ok = true;
} else {
ctr--;
if (ctr != 0) {
ctr_ok = ((bo & 2) == 0);
} else {
ctr_ok = ((bo & 2) != 0);
}
}
return ctr_ok;
}
inline bool
condOk(uint32_t cr) const
{
bool cond_ok;
if (bo & 16) {
cond_ok = true;
} else {
cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1));
}
return cond_ok;
}
};
/**
* Base class for conditional, PC-relative branches.
*/
class BranchPCRelCond : public BranchCond
{
protected:
/// Displacement
uint32_t disp;
/// Constructor.
BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
: BranchCond(mnem, _machInst, __opClass),
disp(machInst.bd << 2)
{
// If bit 16 is 1 then sign extend
if (disp & 0x8000) {
disp |= 0xffff0000;
}
}
Addr branchTarget(Addr pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Base class for conditional, non PC-relative branches.
*/
class BranchNonPCRelCond : public BranchCond
{
protected:
/// Target address
uint32_t targetAddr;
/// Constructor.
BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
: BranchCond(mnem, _machInst, __opClass),
targetAddr(machInst.bd << 2)
{
// If bit 16 is 1 then sign extend
if (targetAddr & 0x8000) {
targetAddr |= 0xffff0000;
}
}
Addr branchTarget(Addr pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Base class for conditional, register-based branches
*/
class BranchRegCond : public BranchCond
{
protected:
/// Constructor.
BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass)
: BranchCond(mnem, _machInst, __opClass)
{
}
Addr branchTarget(ThreadContext *tc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // PowerISA namespace
#endif //__ARCH_POWER_INSTS_BRANCH_HH__

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,33 +24,36 @@
* 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: Timothy M. Jones
*/
/*
* $Id$
*
* */
#include "arch/power/insts/condition.hh"
#include "mem/slicc/symbols/Var.hh"
#include "mem/slicc/symbols/StateMachine.hh"
using namespace PowerISA;
Var::Var(string id, const Location& location,
Type* type_ptr, string code,
const Map<string, string>& pairs,
StateMachine* machine_ptr) : Symbol(id, location, pairs)
std::string
CondLogicOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
if (machine_ptr == NULL) {
m_c_id = id;
} else {
m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name
}
std::stringstream ss;
m_machine_ptr = machine_ptr;
m_type_ptr = type_ptr;
m_code = code;
ccprintf(ss, "%-10s ", mnemonic);
// Format is <mnemonic> bt, ba, bb
ss << bt << ", " << ba << ", " << bb;
return ss.str();
}
void Var::print(ostream& out) const
std::string
CondMoveOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
out << "[Var id: " << m_c_id << "]" << endl;
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
// Format is <mnemonic> bf, bfa
ss << bf << ", " << bfa;
return ss.str();
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,61 +24,63 @@
* 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: Timothy M. Jones
*/
/*
* DeclAST.hh
*
* Description:
*
* $Id$
*
#ifndef __ARCH_POWER_INSTS_CONDITION_HH__
#define __ARCH_POWER_INSTS_CONDITION_HH__
#include "arch/power/insts/static_inst.hh"
#include "base/cprintf.hh"
namespace PowerISA
{
/**
* Class for condition register logical operations.
*/
class CondLogicOp : public PowerStaticInst
{
protected:
#ifndef DECLAST_H
#define DECLAST_H
uint32_t ba;
uint32_t bb;
uint32_t bt;
#include "mem/slicc/slicc_global.hh"
#include "mem/slicc/ast/AST.hh"
#include "mem/slicc/ast/PairListAST.hh"
#include "mem/slicc/symbols/StateMachine.hh"
#include "mem/slicc/ast/TypeAST.hh"
/// Constructor
CondLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PowerStaticInst(mnem, _machInst, __opClass),
ba(machInst.ba),
bb(machInst.bb),
bt(machInst.bt)
{
}
class DeclAST : public AST {
public:
// Constructors
DeclAST(PairListAST* pairs_ptr) : AST(pairs_ptr->getPairs()) {}
// Destructor
virtual ~DeclAST() {}
// Public Methods
virtual void generate() = 0;
virtual void findMachines() {};
// void print(ostream& out) const;
private:
// Private Methods
// Private copy constructor and assignment operator
// DeclAST(const DeclAST& obj);
// DeclAST& operator=(const DeclAST& obj);
// Data Members (m_ prefix)
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
// Output operator declaration
ostream& operator<<(ostream& out, const DeclAST& obj);
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const DeclAST& obj)
/**
* Class for condition register move operations.
*/
class CondMoveOp : public PowerStaticInst
{
obj.print(out);
out << flush;
return out;
}
protected:
#endif //DECLAST_H
uint32_t bf;
uint32_t bfa;
/// Constructor
CondMoveOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PowerStaticInst(mnem, _machInst, __opClass),
bf(machInst.bf),
bfa(machInst.bfa)
{
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // PowerISA namespace
#endif //__ARCH_POWER_INSTS_CONDITION_HH__

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#include "arch/power/insts/floating.hh"
using namespace PowerISA;
std::string
FloatOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
printReg(ss, _destRegIdx[0]);
}
// Print the (possibly) two source registers
if (_numSrcRegs > 0) {
if (_numDestRegs > 0) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
if (_numSrcRegs > 1) {
ss << ", ";
printReg(ss, _srcRegIdx[1]);
}
}
return ss.str();
}

View file

@ -0,0 +1,153 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
* Korey Sewell
*/
#ifndef __ARCH_POWER_INSTS_FLOATING_HH__
#define __ARCH_POWER_INSTS_FLOATING_HH__
#include "arch/power/insts/static_inst.hh"
#include "base/cprintf.hh"
#include "base/bitfield.hh"
namespace PowerISA
{
/**
* Base class for floating point operations.
*/
class FloatOp : public PowerStaticInst
{
protected:
bool rcSet;
/// Constructor
FloatOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PowerStaticInst(mnem, _machInst, __opClass)
{
}
// Test for NaN (maximum biased exponent & non-zero fraction)
inline bool
isNan(uint32_t val_bits) const
{
return ((bits(val_bits, 30, 23) == 0xFF) && bits(val_bits, 22, 0));
}
inline bool
isNan(uint64_t val_bits) const
{
return ((bits(val_bits, 62, 52) == 0x7FF) && bits(val_bits, 51, 0));
}
inline bool
isNan(float val) const
{
void *val_ptr = &val;
uint32_t val_bits = *(uint32_t *) val_ptr;
return isNan(val_bits);
}
inline bool
isNan(double val) const
{
void *val_ptr = &val;
uint64_t val_bits = *(uint64_t *) val_ptr;
return isNan(val_bits);
}
// Test for SNaN (NaN with high order bit of fraction set to 0)
inline bool
isSnan(uint32_t val_bits) const
{
return ((bits(val_bits, 30, 22) == 0x1FE) && bits(val_bits, 22, 0));
}
// Test for QNaN (NaN with high order bit of fraction set to 1)
inline bool
isQnan(uint32_t val_bits) const
{
return (bits(val_bits, 30, 22) == 0x1FF);
}
// Test for infinity (maximum biased exponent and zero fraction)
inline bool
isInfinity(uint32_t val_bits) const
{
return ((bits(val_bits, 30, 23) == 0xFF) && !bits(val_bits, 22, 0));
}
// Test for normalized numbers (biased exponent in the range 1 to 254)
inline bool
isNormalized(uint32_t val_bits) const
{
return ((bits(val_bits, 30, 23) != 0xFF) && bits(val_bits, 22, 0));
}
// Test for denormalized numbers (biased exponent of zero and
// non-zero fraction)
inline bool
isDenormalized(uint32_t val_bits) const
{
return (!bits(val_bits, 30, 23) && bits(val_bits, 22, 0));
}
// Test for zero (biased exponent of zero and fraction of zero)
inline bool
isZero(uint32_t val_bits) const
{
return (!bits(val_bits, 30, 23) && !bits(val_bits, 22, 0));
}
// Test for negative
inline bool
isNegative(uint32_t val_bits) const
{
return (bits(val_bits, 31));
}
// Compute the CR field
inline uint32_t
makeCRField(double a, double b) const
{
uint32_t c = 0;
if (isNan(a) || isNan(b)) { c = 0x1; }
else if (a < b) { c = 0x8; }
else if (a > b) { c = 0x4; }
else { c = 0x2; }
return c;
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // PowerISA namespace
#endif //__ARCH_POWER_INSTS_FLOATING_HH__

View file

@ -0,0 +1,170 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#include "arch/power/insts/integer.hh"
using namespace std;
using namespace PowerISA;
string
IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
stringstream ss;
bool printDest = true;
bool printSrcs = true;
bool printSecondSrc = true;
// Generate the correct mnemonic
string myMnemonic(mnemonic);
// Special cases
if (!myMnemonic.compare("or") && _srcRegIdx[0] == _srcRegIdx[1]) {
myMnemonic = "mr";
printSecondSrc = false;
} else if (!myMnemonic.compare("mtlr") || !myMnemonic.compare("cmpi")) {
printDest = false;
} else if (!myMnemonic.compare("mflr")) {
printSrcs = false;
}
// Additional characters depending on isa bits being set
if (oeSet) myMnemonic = myMnemonic + "o";
if (rcSet) myMnemonic = myMnemonic + ".";
ccprintf(ss, "%-10s ", myMnemonic);
// Print the first destination only
if (_numDestRegs > 0 && printDest) {
printReg(ss, _destRegIdx[0]);
}
// Print the (possibly) two source registers
if (_numSrcRegs > 0 && printSrcs) {
if (_numDestRegs > 0 && printDest) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
if (_numSrcRegs > 1 && printSecondSrc) {
ss << ", ";
printReg(ss, _srcRegIdx[1]);
}
}
return ss.str();
}
string
IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
stringstream ss;
// Generate the correct mnemonic
string myMnemonic(mnemonic);
// Special cases
if (!myMnemonic.compare("addi") && _numSrcRegs == 0) {
myMnemonic = "li";
} else if (!myMnemonic.compare("addis") && _numSrcRegs == 0) {
myMnemonic = "lis";
}
ccprintf(ss, "%-10s ", myMnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
printReg(ss, _destRegIdx[0]);
}
// Print the source register
if (_numSrcRegs > 0) {
if (_numDestRegs > 0) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
}
// Print the immediate value last
ss << ", " << (int32_t)imm;
return ss.str();
}
string
IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
printReg(ss, _destRegIdx[0]);
}
// Print the first source register
if (_numSrcRegs > 0) {
if (_numDestRegs > 0) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
}
// Print the shift
ss << ", " << sh;
return ss.str();
}
string
IntRotateOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
printReg(ss, _destRegIdx[0]);
}
// Print the first source register
if (_numSrcRegs > 0) {
if (_numDestRegs > 0) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
}
// Print the shift, mask begin and mask end
ss << ", " << sh << ", " << mb << ", " << me;
return ss.str();
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#ifndef __ARCH_POWER_INSTS_INTEGER_HH__
#define __ARCH_POWER_INSTS_INTEGER_HH__
#include "arch/power/insts/static_inst.hh"
#include "base/cprintf.hh"
#include "base/bitfield.hh"
namespace PowerISA
{
/**
* We provide a base class for integer operations and then inherit for
* several other classes. These specialise for instructions using immediate
* values and also rotate instructions. We also need to have versions that
* consider the Rc and OE bits.
*/
/**
* Base class for integer operations.
*/
class IntOp : public PowerStaticInst
{
protected:
bool rcSet;
bool oeSet;
// Needed for srawi only
uint32_t sh;
/// Constructor
IntOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PowerStaticInst(mnem, _machInst, __opClass),
rcSet(false), oeSet(false)
{
}
/* Compute the CR (condition register) field using signed comparison */
inline uint32_t
makeCRField(int32_t a, int32_t b, uint32_t xerSO) const
{
uint32_t c = xerSO;
/* We've pre-shifted the immediate values here */
if (a < b) { c += 0x8; }
else if (a > b) { c += 0x4; }
else { c += 0x2; }
return c;
}
/* Compute the CR (condition register) field using unsigned comparison */
inline uint32_t
makeCRField(uint32_t a, uint32_t b, uint32_t xerSO) const
{
uint32_t c = xerSO;
/* We've pre-shifted the immediate values here */
if (a < b) { c += 0x8; }
else if (a > b) { c += 0x4; }
else { c += 0x2; }
return c;
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Class for integer immediate (signed and unsigned) operations.
*/
class IntImmOp : public IntOp
{
protected:
int32_t imm;
uint32_t uimm;
/// Constructor
IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: IntOp(mnem, _machInst, __opClass),
imm(sext<16>(machInst.si)),
uimm(machInst.si)
{
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Class for integer operations with a shift.
*/
class IntShiftOp : public IntOp
{
protected:
uint32_t sh;
/// Constructor
IntShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: IntOp(mnem, _machInst, __opClass),
sh(machInst.sh)
{
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Class for integer rotate operations.
*/
class IntRotateOp : public IntShiftOp
{
protected:
uint32_t mb;
uint32_t me;
uint32_t fullMask;
/// Constructor
IntRotateOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: IntShiftOp(mnem, _machInst, __opClass),
mb(machInst.mb),
me(machInst.me)
{
if (me >= mb) {
fullMask = mask(31 - mb, 31 - me);
} else {
fullMask = ~mask(31 - (me + 1), 31 - (mb - 1));
}
}
uint32_t
rotateValue(uint32_t rs, uint32_t shift) const
{
uint32_t n = shift & 31;
return (rs << n) | (rs >> (32 - n));
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // PowerISA namespace
#endif //__ARCH_POWER_INSTS_INTEGER_HH__

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,62 +24,51 @@
* 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: Timothy M. Jones
*/
/*
* DeclListAST.C
*
* Description: See DeclListAST.hh
*
* $Id$
*
*/
#include "arch/power/insts/mem.hh"
#include "base/loader/symtab.hh"
#include "mem/slicc/ast/DeclListAST.hh"
using namespace PowerISA;
DeclListAST::DeclListAST(Vector<DeclAST*>* vec_ptr)
: AST()
std::string
MemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
assert(vec_ptr != NULL);
m_vec_ptr = vec_ptr;
return csprintf("%-10s", mnemonic);
}
// Singleton constructor.
DeclListAST::DeclListAST(DeclAST* Decl_ptr)
: AST()
std::string
MemDispOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
assert(Decl_ptr != NULL);
m_vec_ptr = new Vector<DeclAST*>;
m_vec_ptr->insertAtTop(Decl_ptr);
}
std::stringstream ss;
DeclListAST::~DeclListAST()
{
int size = m_vec_ptr->size();
for(int i=0; i<size; i++) {
delete (*m_vec_ptr)[i];
}
delete m_vec_ptr;
}
ccprintf(ss, "%-10s ", mnemonic);
void DeclListAST::generate() const
{
int size = m_vec_ptr->size();
for(int i=0; i<size; i++) {
(*m_vec_ptr)[i]->generate();
}
}
// Print the destination only for a load
if (!flags[IsStore]) {
if (_numDestRegs > 0) {
void DeclListAST::findMachines() const
{
int size = m_vec_ptr->size();
for(int i=0; i<size; i++) {
(*m_vec_ptr)[i]->findMachines();
}
}
// If the instruction updates the source register with the
// EA, then this source register is placed in position 0,
// therefore we print the last destination register.
printReg(ss, _destRegIdx[_numDestRegs-1]);
}
}
void DeclListAST::print(ostream& out) const
{
assert(m_vec_ptr != NULL);
out << "[DeclListAST: " << *m_vec_ptr << "]";
// Print the data register for a store
else {
printReg(ss, _srcRegIdx[1]);
}
// Print the displacement
ss << ", " << (int32_t)disp;
// Print the address register
ss << "(";
printReg(ss, _srcRegIdx[0]);
ss << ")";
return ss.str();
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,62 +24,68 @@
* 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: Timothy M. Jones
*/
/*
* TypeDeclAST.C
*
* Description: See TypeDeclAST.hh
*
* $Id: TypeDeclAST.C,v 3.1 2003/03/22 15:15:17 xu Exp $
*
#ifndef __ARCH_POWER_MEM_HH__
#define __ARCH_POWER_MEM_HH__
#include "arch/power/insts/static_inst.hh"
namespace PowerISA
{
/**
* Base class for memory operations.
*/
#include "mem/slicc/ast/TypeDeclAST.hh"
#include "mem/slicc/main.hh"
#include "mem/slicc/symbols/SymbolTable.hh"
TypeDeclAST::TypeDeclAST(TypeAST* type_ast_ptr,
PairListAST* pairs_ptr,
Vector<TypeFieldAST*>* field_vec_ptr)
: DeclAST(pairs_ptr)
class MemOp : public PowerStaticInst
{
m_type_ast_ptr = type_ast_ptr;
m_field_vec_ptr = field_vec_ptr;
}
protected:
TypeDeclAST::~TypeDeclAST()
{
delete m_type_ast_ptr;
if (m_field_vec_ptr != NULL) {
int size = m_field_vec_ptr->size();
for(int i=0; i<size; i++) {
delete (*m_field_vec_ptr)[i];
/// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags;
/// Pointer to EAComp object.
const StaticInstPtr eaCompPtr;
/// Pointer to MemAcc object.
const StaticInstPtr memAccPtr;
/// Constructor
MemOp(const char *mnem, MachInst _machInst, OpClass __opClass,
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: PowerStaticInst(mnem, _machInst, __opClass),
memAccessFlags(0),
eaCompPtr(_eaCompPtr),
memAccPtr(_memAccPtr)
{
}
delete m_field_vec_ptr;
}
}
void TypeDeclAST::generate()
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
* Class for memory operations with displacement.
*/
class MemDispOp : public MemOp
{
string machine_name;
string id = m_type_ast_ptr->toString();
protected:
// Make the new type
Type* new_type_ptr = new Type(id, getLocation(), getPairs(),
g_sym_table.getStateMachine());
g_sym_table.newSym(new_type_ptr);
int16_t disp;
// Add all of the fields of the type to it
if (m_field_vec_ptr != NULL) {
int size = m_field_vec_ptr->size();
for(int i=0; i<size; i++) {
(*m_field_vec_ptr)[i]->generate(new_type_ptr);
/// Constructor
MemDispOp(const char *mnem, MachInst _machInst, OpClass __opClass,
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: MemOp(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
disp(machInst.d)
{
}
}
}
void TypeDeclAST::print(ostream& out) const
{
out << "[TypeDecl: " << m_type_ast_ptr->toString() << "]";
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // PowerISA namespace
#endif //__ARCH_POWER_INSTS_MEM_HH__

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#include "arch/power/insts/misc.hh"
using namespace PowerISA;
std::string
MiscOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
printReg(ss, _destRegIdx[0]);
}
// Print the (possibly) two source registers
if (_numSrcRegs > 0) {
if (_numDestRegs > 0) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
if (_numSrcRegs > 1) {
ss << ", ";
printReg(ss, _srcRegIdx[1]);
}
}
return ss.str();
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,31 +24,34 @@
* 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: Timothy M. Jones
*/
/*
* LiteralExprAST.C
*
* Description: See LiteralExprAST.hh
*
* $Id: LiteralExprAST.C,v 3.1 2002/10/22 21:27:52 milo Exp $
*
*/
#ifndef __ARCH_POWER_INSTS_MISC_HH__
#define __ARCH_POWER_INSTS_MISC_HH__
#include "mem/slicc/ast/LiteralExprAST.hh"
#include "arch/power/insts/static_inst.hh"
Type* LiteralExprAST::generate(string& code) const
namespace PowerISA
{
if (m_type == "string") {
code += "(\"" + *m_lit_ptr + "\")";
} else {
code += "(" + *m_lit_ptr + ")";
}
Type* type_ptr = g_sym_table.getType(m_type);
if (type_ptr == NULL) {
// Can't find the type
error("Internal: can't primitive type '" + m_type + "'");
}
return type_ptr;
}
/**
* Class for misc operations.
*/
class MiscOp : public PowerStaticInst
{
protected:
/// Constructor
MiscOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PowerStaticInst(mnem, _machInst, __opClass)
{
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // PowerISA namespace
#endif //__ARCH_POWER_INSTS_MISC_HH__

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2009 The University of Edinburgh
* 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: Timothy M. Jones
*/
#include "arch/power/insts/static_inst.hh"
using namespace PowerISA;
void
PowerStaticInst::printReg(std::ostream &os, int reg) const
{
if (reg < FP_Base_DepTag) {
ccprintf(os, "r%d", reg);
} else if (reg < Ctrl_Base_DepTag) {
ccprintf(os, "f%d", reg - FP_Base_DepTag);
} else {
switch (reg - Ctrl_Base_DepTag) {
case 0: ccprintf(os, "cr"); break;
case 1: ccprintf(os, "xer"); break;
case 2: ccprintf(os, "lr"); break;
case 3: ccprintf(os, "ctr"); break;
default: ccprintf(os, "unknown_reg");
}
}
}
std::string
PowerStaticInst::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
ccprintf(ss, "%-10s ", mnemonic);
return ss.str();
}

View file

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,58 +24,47 @@
* 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: Timothy M. Jones
*/
/*
* PairListAST.hh
*
* Description:
*
* $Id$
*
*/
#ifndef __ARCH_POWER_INSTS_STATICINST_HH__
#define __ARCH_POWER_INSTS_STATICINST_HH__
#ifndef PairListAST_H
#define PairListAST_H
#include "base/trace.hh"
#include "cpu/static_inst.hh"
#include "mem/slicc/slicc_global.hh"
#include "mem/slicc/ast/AST.hh"
#include "mem/slicc/ast/PairAST.hh"
namespace PowerISA
{
class PowerStaticInst : public StaticInst
{
protected:
class PairListAST : public AST {
public:
// Constructors
PairListAST() : AST() {}
// Constructor
PowerStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
: StaticInst(mnem, _machInst, __opClass)
{
}
// Destructor
//~PairListAST();
// Insert a condition value into a CR (condition register) field
inline uint32_t
insertCRField(uint32_t cr, uint32_t bf, uint32_t value) const
{
uint32_t bits = value << ((7 - bf) * 4);
uint32_t mask = ~(0xf << ((7 - bf) * 4));
return (cr & mask) | bits;
}
// Public Methods
void addPair(PairAST* pair_ptr);
void print(ostream& out) const;
private:
// Private Methods
/// Print a register name for disassembly given the unique
/// dependence tag number (FP or int).
void
printReg(std::ostream &os, int reg) const;
// Private copy constructor and assignment operator
PairListAST(const PairListAST& obj);
PairListAST& operator=(const PairListAST& obj);
// Data Members (m_ prefix)
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
// Output operator declaration
ostream& operator<<(ostream& out, const PairListAST& obj);
} // PowerISA namespace
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const PairListAST& obj)
{
obj.print(out);
out << flush;
return out;
}
#endif //PairListAST_H
#endif //__ARCH_POWER_INSTS_STATICINST_HH__

115
src/arch/power/isa.hh Normal file
View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2009 The Regents of The University of Michigan
* Copyright (c) 2009 The University of Edinburgh
* 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
* Timothy M. Jones
*/
#ifndef __ARCH_POWER_ISA_HH__
#define __ARCH_POWER_ISA_HH__
#include "arch/power/registers.hh"
#include "arch/power/types.hh"
#include "base/misc.hh"
class ThreadContext;
class Checkpoint;
class EventManager;
namespace PowerISA
{
class ISA
{
protected:
MiscReg dummy;
MiscReg miscRegs[NumMiscRegs];
public:
void
clear()
{
}
MiscReg
readMiscRegNoEffect(int misc_reg)
{
fatal("Power does not currently have any misc regs defined\n");
return dummy;
}
MiscReg
readMiscReg(int misc_reg, ThreadContext *tc)
{
fatal("Power does not currently have any misc regs defined\n");
return dummy;
}
void
setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
fatal("Power does not currently have any misc regs defined\n");
}
void
setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{
fatal("Power does not currently have any misc regs defined\n");
}
int
flattenIntIndex(int reg)
{
return reg;
}
int
flattenFloatIndex(int reg)
{
return reg;
}
void
serialize(EventManager *em, std::ostream &os)
{
}
void
unserialize(EventManager *em, Checkpoint *cp, const std::string &section)
{
}
ISA()
{
clear();
}
};
} // PowerISA namespace
#endif // __ARCH_POWER_ISA_HH__

Some files were not shown because too many files have changed in this diff Show more