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 *.pyc
*~ *~
.*.swp .*.swp
m5out

View file

@ -96,6 +96,7 @@ For more details, see:
""" """
raise raise
# Global Python includes
import os import os
import re import re
import subprocess 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 exists, isdir, isfile
from os.path import join as joinpath, split as splitpath from os.path import join as joinpath, split as splitpath
# SCons includes
import SCons import SCons
import SCons.Node import SCons.Node
def read_command(cmd, **kwargs): extra_python_paths = [
"""run the command cmd, read the results and return them Dir('src/python').srcnode().abspath, # M5 includes
this is sorta like `cmd` in shell""" Dir('ext/ply').srcnode().abspath, # ply is used by several files
from subprocess import Popen, PIPE, STDOUT ]
if isinstance(cmd, str):
cmd = cmd.split()
no_exception = 'exception' in kwargs
exception = kwargs.pop('exception', None)
kwargs.setdefault('shell', False) sys.path[1:1] = extra_python_paths
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
return subp.communicate()[0] from m5.util import compareVersions, readCommand
# 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
######################################################################## ########################################################################
# #
@ -162,7 +126,7 @@ def compare_versions(v1, v2):
# #
######################################################################## ########################################################################
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH', use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
'RANLIB' ]) 'PYTHONPATH', 'RANLIB' ])
use_env = {} use_env = {}
for key,val in os.environ.iteritems(): 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.root = Dir(".") # The current directory (where this file lives).
main.srcdir = Dir("src") # The source directory 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. # Mercurial Stuff.
@ -217,7 +185,7 @@ if hgdir.exists():
# 1) Grab repository revision if we know it. # 1) Grab repository revision if we know it.
cmd = "hg id -n -i -t -b" cmd = "hg id -n -i -t -b"
try: try:
hg_info = read_command(cmd, cwd=main.root.abspath).strip() hg_info = readCommand(cmd, cwd=main.root.abspath).strip()
except OSError: except OSError:
print mercurial_bin_not_found print mercurial_bin_not_found
@ -378,11 +346,8 @@ Export('extras_dir_list')
# the ext directory should be on the #includes path # the ext directory should be on the #includes path
main.Append(CPPPATH=[Dir('ext')]) main.Append(CPPPATH=[Dir('ext')])
# M5_PLY is used by isa_parser.py to find the PLY package. CXX_version = readCommand([main['CXX'],'--version'], exception=False)
main.Append(ENV = { 'M5_PLY' : Dir('ext/ply').abspath }) CXX_V = readCommand([main['CXX'],'-V'], exception=False)
CXX_version = read_command([main['CXX'],'--version'], exception=False)
CXX_V = read_command([main['CXX'],'-V'], exception=False)
main['GCC'] = CXX_version and CXX_version.find('g++') >= 0 main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0 main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
@ -426,7 +391,7 @@ if main['BATCH']:
if sys.platform == 'cygwin': if sys.platform == 'cygwin':
# cygwin has some header file issues... # cygwin has some header file issues...
main.Append(CCFLAGS=Split("-Wno-uninitialized")) main.Append(CCFLAGS="-Wno-uninitialized")
# Check for SWIG # Check for SWIG
if not main.has_key('SWIG'): if not main.has_key('SWIG'):
@ -435,7 +400,7 @@ if not main.has_key('SWIG'):
Exit(1) Exit(1)
# Check for appropriate SWIG version # 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" # First 3 words should be "SWIG Version x.y.z"
if len(swig_version) < 3 or \ if len(swig_version) < 3 or \
swig_version[0] != 'SWIG' or swig_version[1] != 'Version': swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
@ -443,7 +408,7 @@ if len(swig_version) < 3 or \
Exit(1) Exit(1)
min_swig_version = '1.3.28' 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 'Error: SWIG version', min_swig_version, 'or newer required.'
print ' Installed version:', swig_version[2] print ' Installed version:', swig_version[2]
Exit(1) Exit(1)
@ -514,8 +479,8 @@ conf.CheckLeading()
try: try:
import platform import platform
uname = platform.uname() uname = platform.uname()
if uname[0] == 'Darwin' and compare_versions(uname[2], '9.0.0') >= 0: if uname[0] == 'Darwin' and compareVersions(uname[2], '9.0.0') >= 0:
if int(read_command('sysctl -n hw.cpu64bit_capable')[0]): if int(readCommand('sysctl -n hw.cpu64bit_capable')[0]):
main.Append(CCFLAGS='-arch x86_64') main.Append(CCFLAGS='-arch x86_64')
main.Append(CFLAGS='-arch x86_64') main.Append(CFLAGS='-arch x86_64')
main.Append(LINKFLAGS='-arch x86_64') main.Append(LINKFLAGS='-arch x86_64')
@ -615,9 +580,9 @@ have_mysql = bool(mysql_config)
# Check MySQL version. # Check MySQL version.
if have_mysql: if have_mysql:
mysql_version = read_command(mysql_config + ' --version') mysql_version = readCommand(mysql_config + ' --version')
min_mysql_version = '4.1' 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 'Warning: MySQL', min_mysql_version, 'or newer required.'
print ' Version', mysql_version, 'detected.' print ' Version', mysql_version, 'detected.'
have_mysql = False have_mysql = False
@ -777,17 +742,10 @@ def make_switching_dir(dname, switch_headers, env):
# list of ISAs from env['ALL_ISA_LIST']. # list of ISAs from env['ALL_ISA_LIST'].
def gen_switch_hdr(target, source, env): def gen_switch_hdr(target, source, env):
fname = str(target[0]) fname = str(target[0])
bname = basename(fname)
f = open(fname, 'w') f = open(fname, 'w')
f.write('#include "arch/isa_specific.hh"\n') isa = env['TARGET_ISA'].lower()
cond = '#if' print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
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')
f.close() f.close()
return 0
# String to print when generating header # String to print when generating header
def gen_switch_hdr_string(target, source, env): 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 # Authors: Lisa Hsu
import m5
from m5.objects import * from m5.objects import *
class L1Cache(BaseCache): class L1Cache(BaseCache):

View file

@ -26,8 +26,6 @@
# #
# Authors: Kevin Lim # Authors: Kevin Lim
import m5
from m5 import makeList
from m5.objects import * from m5.objects import *
from Benchmarks import * from Benchmarks import *
@ -81,6 +79,50 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
return self 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): def makeSparcSystem(mem_mode, mdesc = None):
class CowMmDisk(MmDisk): class CowMmDisk(MmDisk):
image = CowDiskImage(child=RawDiskImage(read_only=True), image = CowDiskImage(child=RawDiskImage(read_only=True),

View file

@ -38,6 +38,7 @@ parser.add_option("--fastmem", action="store_true")
# Run duration options # Run duration options
parser.add_option("-m", "--maxtick", type="int") parser.add_option("-m", "--maxtick", type="int")
parser.add_option("--maxtime", type="float") parser.add_option("--maxtime", type="float")
parser.add_option("--maxinsts", type="int")
parser.add_option("--prog_intvl", 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") help="Place all checkpoints in this absolute directory")
parser.add_option("-r", "--checkpoint-restore", action="store", type="int", parser.add_option("-r", "--checkpoint-restore", action="store", type="int",
help="restore from checkpoint <N>") 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 # CPU Switching - default switch model goes from a checkpoint
# to a timing simple CPU with caches to warm up, then to detailed CPU for # 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", parser.add_option("-w", "--warmup", action="store", type="int",
help="if -s, then this is the warmup period. else, this is ignored", help="if -s, then this is the warmup period. else, this is ignored",
default=5000000000) default=5000000000)
parser.add_option("--profile", help="CPU profile interval")
# Fastforwarding and simpoint related materials # Fastforwarding and simpoint related materials
parser.add_option("-W", "--warmup-insts", action="store", type="int", parser.add_option("-W", "--warmup-insts", action="store", type="int",

View file

@ -28,9 +28,13 @@
from os import getcwd from os import getcwd
from os.path import join as joinpath from os.path import join as joinpath
import m5 import m5
from m5.defines import buildEnv
from m5.objects import * from m5.objects import *
m5.AddToPath('../common') from m5.util import *
addToPath('../common')
def setCPUClass(options): def setCPUClass(options):
@ -82,10 +86,10 @@ def run(options, root, testsys, cpu_class):
cptdir = getcwd() cptdir = getcwd()
if options.fast_forward and options.checkpoint_restore != None: 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: 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 np = options.num_cpus
max_checkpoints = options.max_checkpoints max_checkpoints = options.max_checkpoints
@ -95,6 +99,10 @@ def run(options, root, testsys, cpu_class):
for i in xrange(np): for i in xrange(np):
testsys.cpu[i].progress_interval = options.prog_intvl 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: if cpu_class:
switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i)) switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
for i in xrange(np)] for i in xrange(np)]
@ -103,7 +111,7 @@ def run(options, root, testsys, cpu_class):
if options.fast_forward: if options.fast_forward:
testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
switch_cpus[i].system = testsys 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].workload = testsys.cpu[i].workload
switch_cpus[i].clock = testsys.cpu[0].clock switch_cpus[i].clock = testsys.cpu[0].clock
# simulation period # simulation period
@ -122,7 +130,7 @@ def run(options, root, testsys, cpu_class):
for i in xrange(np): for i in xrange(np):
switch_cpus[i].system = testsys switch_cpus[i].system = testsys
switch_cpus_1[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[i].workload = testsys.cpu[i].workload
switch_cpus_1[i].workload = testsys.cpu[i].workload switch_cpus_1[i].workload = testsys.cpu[i].workload
switch_cpus[i].clock = testsys.cpu[0].clock switch_cpus[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) # Fast forward to a simpoint (warning: time consuming)
elif options.simpoint: elif options.simpoint:
if testsys.cpu[i].workload[0].simpoint == 0: 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].max_insts_any_thread = \
testsys.cpu[i].workload[0].simpoint testsys.cpu[i].workload[0].simpoint
# No distance specified, just switch # No distance specified, just switch
@ -170,7 +178,7 @@ def run(options, root, testsys, cpu_class):
if options.simpoint: if options.simpoint:
for i in xrange(np): for i in xrange(np):
if testsys.cpu[i].workload[0].simpoint == 0: 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 checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
testsys.cpu[i].max_insts_any_thread = checkpoint_inst testsys.cpu[i].max_insts_any_thread = checkpoint_inst
# used for output below # used for output below
@ -190,14 +198,13 @@ def run(options, root, testsys, cpu_class):
import re import re
if not isdir(cptdir): 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: if options.at_instruction:
checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \ checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
(options.bench, options.checkpoint_restore)) (options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir): if not exists(checkpoint_dir):
m5.fatal("Unable to find checkpoint directory %s", fatal("Unable to find checkpoint directory %s", checkpoint_dir)
checkpoint_dir)
print "Restoring checkpoint ..." print "Restoring checkpoint ..."
m5.restoreCheckpoint(root, checkpoint_dir) m5.restoreCheckpoint(root, checkpoint_dir)
@ -205,7 +212,7 @@ def run(options, root, testsys, cpu_class):
elif options.simpoint: elif options.simpoint:
# assume workload 0 has the simpoint # assume workload 0 has the simpoint
if testsys.cpu[0].workload[0].simpoint == 0: if testsys.cpu[0].workload[0].simpoint == 0:
m5.fatal('Unable to find simpoint') fatal('Unable to find simpoint')
options.checkpoint_restore += \ options.checkpoint_restore += \
int(testsys.cpu[0].workload[0].simpoint) 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" % \ checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
(options.bench, options.checkpoint_restore)) (options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir): if not exists(checkpoint_dir):
m5.fatal("Unable to find checkpoint directory %s.%s", fatal("Unable to find checkpoint directory %s.%s",
options.bench, options.checkpoint_restore) options.bench, options.checkpoint_restore)
print "Restoring checkpoint ..." print "Restoring checkpoint ..."
m5.restoreCheckpoint(root,checkpoint_dir) m5.restoreCheckpoint(root,checkpoint_dir)
@ -233,7 +240,7 @@ def run(options, root, testsys, cpu_class):
cpt_num = options.checkpoint_restore cpt_num = options.checkpoint_restore
if cpt_num > len(cpts): 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 ## Adjust max tick based on our starting tick
maxtick = maxtick - int(cpts[cpt_num - 1]) maxtick = maxtick - int(cpts[cpt_num - 1])
@ -367,3 +374,6 @@ def run(options, root, testsys, cpu_class):
exit_cause = exit_event.getCause() exit_cause = exit_event.getCause()
print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause) 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 # Authors: Ali Saidi
import optparse, os, sys import optparse
import os
import sys
import m5 import m5
from m5.defines import buildEnv
if not m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires full-system mode (*_FS).")
from m5.objects import * 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 FSConfig import *
from SysPaths import * from SysPaths import *
from Benchmarks import * from Benchmarks import *
@ -98,16 +103,16 @@ else:
np = options.num_cpus np = options.num_cpus
if m5.build_env['TARGET_ISA'] == "alpha": if buildEnv['TARGET_ISA'] == "alpha":
test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0]) 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]) 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]) 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]) test_sys = makeLinuxX86System(test_mem_mode, np, bm[0])
else: 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: if options.kernel is not None:
test_sys.kernel = binary(options.kernel) 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)] 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_a=[AddrRange(0, Addr.max)]
test_sys.bridge.filter_ranges_b=[AddrRange(0, size='8GB')] test_sys.bridge.filter_ranges_b=[AddrRange(0, size='8GB')]
test_sys.iocache = IOCache(addr_range=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: if options.fastmem:
test_sys.cpu[i].physmem_port = test_sys.physmem.port test_sys.cpu[i].physmem_port = test_sys.physmem.port
if m5.build_env['TARGET_ISA'] == 'mips': if buildEnv['TARGET_ISA'] == 'mips':
setMipsOptions(TestCPUClass) setMipsOptions(TestCPUClass)
if len(bm) == 2: if len(bm) == 2:
if m5.build_env['TARGET_ISA'] == 'alpha': if buildEnv['TARGET_ISA'] == 'alpha':
drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1]) 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]) 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]) 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 = makeX86System(drive_mem_mode, np, bm[1])
drive_sys.cpu = DriveCPUClass(cpu_id=0) drive_sys.cpu = DriveCPUClass(cpu_id=0)
drive_sys.cpu.connectMemPorts(drive_sys.membus) 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 # Authors: Ron Dreslinski
import optparse
import sys
import m5 import m5
from m5.objects import * from m5.objects import *
import os, optparse, sys
m5.AddToPath('../common')
parser = optparse.OptionParser() 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" # "m5 test.py"
import m5 import os
import optparse
if m5.build_env['FULL_SYSTEM']: import sys
m5.panic("This script requires syscall emulation mode (*_SE).")
from m5.objects import *
import os, optparse, sys
from os.path import join as joinpath 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 import Simulation
#from Caches import *
from cpu2000 import * from cpu2000 import *
# Get paths we might need. It's expected this file is in m5/configs/example. # Get paths we might need. It's expected this file is in m5/configs/example.
@ -72,7 +77,7 @@ if args:
if options.bench: if options.bench:
try: 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" print >>sys.stderr, "Simpoints code only works for Alpha ISA at this time"
sys.exit(1) sys.exit(1)
exec("workload = %s('alpha', 'tru64', 'ref')" % options.bench) exec("workload = %s('alpha', 'tru64', 'ref')" % options.bench)
@ -133,7 +138,6 @@ rubymem = RubyMemory(
range = AddrRange("512MB"), range = AddrRange("512MB"),
clock = "1GHz", clock = "1GHz",
num_cpus = np, num_cpus = np,
libruby_file = "src/mem/ruby/amd64-linux/generated/MOESI_CMP_directory/bin/libruby.so",
config_file = "ruby.config", config_file = "ruby.config",
stats_file = "m5out/ruby.stats" stats_file = "m5out/ruby.stats"
) )

View file

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

View file

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

View file

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

View file

@ -49,7 +49,7 @@ Import('*')
# Children need to see the environment # Children need to see the environment
Export('env') 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 # Code for adding source files of various types
@ -132,15 +132,15 @@ class PySource(SourceFile):
modpath = '.'.join(modpath) modpath = '.'.join(modpath)
arcpath = path + [ self.basename ] arcpath = path + [ self.basename ]
debugname = self.snode.abspath abspath = self.snode.abspath
if not exists(debugname): if not exists(abspath):
debugname = self.tnode.abspath abspath = self.tnode.abspath
self.package = package self.package = package
self.modname = modname self.modname = modname
self.modpath = modpath self.modpath = modpath
self.arcname = joinpath(*arcpath) self.arcname = joinpath(*arcpath)
self.debugname = debugname self.abspath = abspath
self.compiled = File(self.filename + 'c') self.compiled = File(self.filename + 'c')
self.assembly = File(self.filename + '.s') self.assembly = File(self.filename + '.s')
self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath) self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath)
@ -228,9 +228,6 @@ env.Append(CPPPATH=Dir('.'))
for extra_dir in extras_dir_list: for extra_dir in extras_dir_list:
env.Append(CPPPATH=Dir(extra_dir)) 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 # Workaround for bug in SCons version > 0.97d20071212
# Scons bug id: 2006 M5 Bug id: 308 # Scons bug id: 2006 M5 Bug id: 308
for root, dirs, files in os.walk(base_dir, topdown=True): 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: for opt in export_vars:
env.ConfigFile(opt) 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 # Prevent any SimObjects from being added after this point, they
# should all have been added in the SConscripts above # should all have been added in the SConscripts above
# #
SimObject.fixed = True
class DictImporter(object): class DictImporter(object):
'''This importer takes a dictionary of arbitrary module names that '''This importer takes a dictionary of arbitrary module names that
map to arbitrary filenames.''' map to arbitrary filenames.'''
@ -283,7 +307,7 @@ class DictImporter(object):
self.installed = set() self.installed = set()
def find_module(self, fullname, path): def find_module(self, fullname, path):
if fullname == 'defines': if fullname == 'm5.defines':
return self return self
if fullname == 'm5.objects': if fullname == 'm5.objects':
@ -293,7 +317,7 @@ class DictImporter(object):
return None return None
source = self.modules.get(fullname, 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 self
return None return None
@ -308,28 +332,31 @@ class DictImporter(object):
mod.__path__ = fullname.split('.') mod.__path__ = fullname.split('.')
return mod return mod
if fullname == 'defines': if fullname == 'm5.defines':
mod.__dict__['buildEnv'] = build_env mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
return mod return mod
source = self.modules[fullname] source = self.modules[fullname]
if source.modname == '__init__': if source.modname == '__init__':
mod.__path__ = source.modpath 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 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 # install the python importer so we can grab stuff from the source
# tree itself. We can't have SimObjects added after this point or # tree itself. We can't have SimObjects added after this point or
# else we won't know about them for the rest of the stuff. # else we won't know about them for the rest of the stuff.
SimObject.fixed = True
importer = DictImporter(PySource.modules) importer = DictImporter(PySource.modules)
sys.meta_path[0:0] = [ importer ] sys.meta_path[0:0] = [ importer ]
import m5
# import all sim objects so we can populate the all_objects list # import all sim objects so we can populate the all_objects list
# make sure that we're working with a list, then let's sort it # make sure that we're working with a list, then let's sort it
for modname in SimObject.modnames: for modname in SimObject.modnames:
@ -346,6 +373,12 @@ all_enums = m5.params.allEnums
all_params = {} all_params = {}
for name,obj in sorted(sim_objects.iteritems()): for name,obj in sorted(sim_objects.iteritems()):
for param in obj._params.local.values(): for param in obj._params.local.values():
# 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'): if not hasattr(param, 'swig_decl'):
continue continue
pname = param.ptype_str 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 # Generate Python file containing a dict specifying the current
# build_env flags. # buildEnv flags.
def makeDefinesPyFile(target, source, env): def makeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
build_env, hg_info = [ x.get_contents() for x in source ] build_env, hg_info = [ x.get_contents() for x in source ]
print >>f, "buildEnv = %s" % build_env
print >>f, "hgRev = '%s'" % hg_info code = m5.util.code_formatter()
f.close() 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']) ] defines_info = [ Value(build_env), Value(env['HG_INFO']) ]
# Generate a file with all of the compile options in it # 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 # Generate any parameter header files needed
params_i_files = [] params_i_files = []
for name,param in all_params.iteritems(): for name,param in all_params.iteritems():
if isinstance(param, m5.params.VectorParamDesc): i_file = File('params/%s_%s.i' % (name, param.file_ext))
ext = 'vptype'
else:
ext = 'ptype'
i_file = File('params/%s_%s.i' % (name, ext))
params_i_files.append(i_file) params_i_files.append(i_file)
env.Command(i_file, Value(name), createSwigParam) env.Command(i_file, Value(name), createSwigParam)
env.Depends(i_file, depends) env.Depends(i_file, depends)
@ -850,7 +892,7 @@ def objectifyPyFile(target, source, env):
dst = file(str(target[0]), 'w') dst = file(str(target[0]), 'w')
pysource = PySource.tnodes[source[0]] pysource = PySource.tnodes[source[0]]
compiled = compile(src, pysource.debugname, 'exec') compiled = compile(src, pysource.abspath, 'exec')
marshalled = marshal.dumps(compiled) marshalled = marshal.dumps(compiled)
compressed = zlib.compress(marshalled) compressed = zlib.compress(marshalled)
data = compressed data = compressed

View file

@ -144,7 +144,7 @@ DtbFault::invoke(ThreadContext *tc)
// read, like the EV5). The EV6 approach is cleaner and seems to // read, like the EV5). The EV6 approach is cleaner and seems to
// work with EV5 PAL code, but not the other way around. // work with EV5 PAL code, but not the other way around.
if (!tc->misspeculating() && if (!tc->misspeculating() &&
reqFlags.noneSet(Request::VPTE|Request::NO_FAULT)) { reqFlags.noneSet(Request::VPTE | Request::PREFETCH)) {
// set VA register with faulting address // set VA register with faulting address
tc->setMiscRegNoEffect(IPR_VA, vaddr); tc->setMiscRegNoEffect(IPR_VA, vaddr);

View file

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

View file

@ -83,8 +83,9 @@ namespace AlphaISA
intr_flag = 0; intr_flag = 0;
} }
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);
void reset(std::string core_name, ThreadID num_threads, void reset(std::string core_name, ThreadID num_threads,
unsigned num_vpes, BaseCPU *_cpu) unsigned num_vpes, BaseCPU *_cpu)

View file

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

View file

@ -548,7 +548,7 @@ def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
pf_flags = makeList(pf_flags) pf_flags = makeList(pf_flags)
inst_flags = makeList(inst_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', pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
'IsDataPrefetch', 'MemReadOp'] 'IsDataPrefetch', 'MemReadOp']

View file

@ -105,6 +105,7 @@ class AlphaLinux : public Linux
static const unsigned TIOCISATTY_ = 0x2000745e; static const unsigned TIOCISATTY_ = 0x2000745e;
static const unsigned TIOCGETS_ = 0x402c7413; static const unsigned TIOCGETS_ = 0x402c7413;
static const unsigned TIOCGETA_ = 0x40127417; static const unsigned TIOCGETA_ = 0x40127417;
static const unsigned TCSETAW_ = 0x80147419; // 2.6.15 kernel
//@} //@}
/// For table(). /// For table().
@ -125,6 +126,21 @@ class AlphaLinux : public Linux
TGT_RLIMIT_MEMLOCK = 9, TGT_RLIMIT_MEMLOCK = 9,
TGT_RLIMIT_LOCKS = 10 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__ #endif // __ALPHA_ALPHA_LINUX_LINUX_HH__

View file

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

View file

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

View file

@ -44,7 +44,7 @@ class AlphaLiveProcess : public LiveProcess
void argsInit(int intSize, int pageSize); void argsInit(int intSize, int pageSize);
public: 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 setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
}; };

View file

@ -45,7 +45,8 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) 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->sysname, "OSF1");
strcpy(name->nodename, "m5.eecs.umich.edu"); strcpy(name->nodename, "m5.eecs.umich.edu");
@ -62,35 +63,36 @@ static SyscallReturn
getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
unsigned op = process->getSyscallArg(tc, 0); int index = 0;
unsigned nbytes = process->getSyscallArg(tc, 2); unsigned op = process->getSyscallArg(tc, index);
Addr bufPtr = process->getSyscallArg(tc, index);
unsigned nbytes = process->getSyscallArg(tc, index);
switch (op) { switch (op) {
case AlphaTru64::GSI_MAX_CPU: { 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 = htog((uint32_t)process->numCpus());
max_cpu.copyOut(tc->getMemPort()); max_cpu.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_CPUS_IN_BOX: { 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 = htog((uint32_t)process->numCpus());
cpus_in_box.copyOut(tc->getMemPort()); cpus_in_box.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_PHYSMEM: { 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 = htog((uint64_t)1024 * 1024); // physical memory in KB
physmem.copyOut(tc->getMemPort()); physmem.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_CPU_INFO: { case AlphaTru64::GSI_CPU_INFO: {
TypedBufferArg<AlphaTru64::cpu_info> TypedBufferArg<AlphaTru64::cpu_info> infop(bufPtr);
infop(process->getSyscallArg(tc, 1));
infop->current_cpu = htog(0); infop->current_cpu = htog(0);
infop->cpus_in_box = htog(process->numCpus()); infop->cpus_in_box = htog(process->numCpus());
@ -107,14 +109,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
} }
case AlphaTru64::GSI_PROC_TYPE: { 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 = htog((uint64_t)11);
proc_type.copyOut(tc->getMemPort()); proc_type.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_PLATFORM_NAME: { case AlphaTru64::GSI_PLATFORM_NAME: {
BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes); BufferArg bufArg(bufPtr, nbytes);
strncpy((char *)bufArg.bufferPtr(), strncpy((char *)bufArg.bufferPtr(),
"COMPAQ Professional Workstation XP1000", "COMPAQ Professional Workstation XP1000",
nbytes); nbytes);
@ -123,7 +125,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
} }
case AlphaTru64::GSI_CLK_TCK: { 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 = htog((uint64_t)1024);
clk_hz.copyOut(tc->getMemPort()); clk_hz.copyOut(tc->getMemPort());
return 1; return 1;
@ -142,12 +144,13 @@ static SyscallReturn
setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
unsigned op = process->getSyscallArg(tc, 0); int index = 0;
unsigned op = process->getSyscallArg(tc, index);
switch (op) { switch (op) {
case AlphaTru64::SSI_IEEE_FP_CONTROL: case AlphaTru64::SSI_IEEE_FP_CONTROL:
warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
process->getSyscallArg(tc, 1)); process->getSyscallArg(tc, index));
break; break;
default: default:
@ -165,17 +168,19 @@ tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{ {
using namespace std; using namespace std;
int id = process->getSyscallArg(tc, 0); // table ID int argIndex = 0;
int index = process->getSyscallArg(tc, 1); // index into table 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 // arg 2 is buffer pointer; type depends on table ID
int nel = process->getSyscallArg(tc, 3); // number of elements int nel = process->getSyscallArg(tc, argIndex); // number of elements
int lel = process->getSyscallArg(tc, 4); // expected element size int lel = process->getSyscallArg(tc, argIndex); // expected element size
switch (id) { switch (id) {
case AlphaTru64::TBL_SYSINFO: { case AlphaTru64::TBL_SYSINFO: {
if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
return -EINVAL; return -EINVAL;
TypedBufferArg<Tru64::tbl_sysinfo> elp(process->getSyscallArg(tc, 2)); TypedBufferArg<Tru64::tbl_sysinfo> elp(bufPtr);
const int clk_hz = one_million; const int clk_hz = one_million;
elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); 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 TIOCISATTY_ = 0x2000745e;
static const unsigned TIOCGETS_ = 0x402c7413; static const unsigned TIOCGETS_ = 0x402c7413;
static const unsigned TIOCGETA_ = 0x40127417; 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. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # 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 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
# Authors: Nathan Binkert # Authors: Ali Saidi
# Steve Reinhardt
import os from m5.params import *
# import the m5 compile options from System import System
import defines
# make a SmartDict out of the build options for our local use class ArmSystem(System):
import smartdict type = 'ArmSystem'
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)

View file

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

View file

@ -26,488 +26,114 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Authors: Gabe Black * Authors: Ali Saidi
* Stephen Hines * Gabe Black
*/ */
#include "arch/arm/faults.hh" #include "arch/arm/faults.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "cpu/base.hh" #include "cpu/base.hh"
#include "base/trace.hh" #include "base/trace.hh"
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace ArmISA namespace ArmISA
{ {
FaultName MachineCheckFault::_name = "Machine Check"; template<> ArmFaultBase::FaultVals ArmFault<Reset>::vals =
FaultVect MachineCheckFault::_vect = 0x0401; {"reset", 0x00, MODE_SVC, 0, 0, true, true};
FaultStat MachineCheckFault::_count;
FaultName AlignmentFault::_name = "Alignment"; template<> ArmFaultBase::FaultVals ArmFault<UndefinedInstruction>::vals =
FaultVect AlignmentFault::_vect = 0x0301; {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ;
FaultStat AlignmentFault::_count;
FaultName ResetFault::_name = "Reset Fault"; template<> ArmFaultBase::FaultVals ArmFault<SupervisorCall>::vals =
#if FULL_SYSTEM {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false};
FaultVect ResetFault::_vect = 0xBFC00000;
#else
FaultVect ResetFault::_vect = 0x001;
#endif
FaultStat ResetFault::_count;
FaultName AddressErrorFault::_name = "Address Error"; template<> ArmFaultBase::FaultVals ArmFault<PrefetchAbort>::vals =
FaultVect AddressErrorFault::_vect = 0x0180; {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false};
FaultStat AddressErrorFault::_count;
FaultName StoreAddressErrorFault::_name = "Store Address Error"; template<> ArmFaultBase::FaultVals ArmFault<DataAbort>::vals =
FaultVect StoreAddressErrorFault::_vect = 0x0180; {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false};
FaultStat StoreAddressErrorFault::_count;
template<> ArmFaultBase::FaultVals ArmFault<Interrupt>::vals =
{"IRQ", 0x18, MODE_IRQ, 4, 4, true, false};
FaultName SystemCallFault::_name = "Syscall"; template<> ArmFaultBase::FaultVals ArmFault<FastInterrupt>::vals =
FaultVect SystemCallFault::_vect = 0x0180; {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
FaultStat SystemCallFault::_count;
FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault"; Addr
FaultVect CoprocessorUnusableFault::_vect = 0x180; ArmFaultBase::getVector(ThreadContext *tc)
FaultStat CoprocessorUnusableFault::_count; {
// ARM ARM B1-3
FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault"; SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
FaultVect ReservedInstructionFault::_vect = 0x0180;
FaultStat ReservedInstructionFault::_count; // 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 #if FULL_SYSTEM
void ArmFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
void
ArmFaultBase::invoke(ThreadContext *tc)
{ {
tc->setPC(HandlerBase); // ARM ARM B1.6.3
tc->setNextPC(HandlerBase+sizeof(MachInst)); FaultBase::invoke(tc);
tc->setNextNPC(HandlerBase+2*sizeof(MachInst)); 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 #endif // FULL_SYSTEM
void ResetFault::invoke(ThreadContext *tc) // return via SUBS pc, lr, xxx; rfe, movs, ldm
{
#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
// 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 } // namespace ArmISA

View file

@ -26,548 +26,79 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Authors: Gabe Black * Authors: Ali Saidi
* Stephen Hines * Gabe Black
*/ */
#ifndef __ARM_FAULTS_HH__ #ifndef __ARM_FAULTS_HH__
#define __ARM_FAULTS_HH__ #define __ARM_FAULTS_HH__
#include "arch/arm/types.hh"
#include "config/full_system.hh"
#include "sim/faults.hh" #include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh // The design of the "name" and "vect" functions is in sim/faults.hh
namespace ArmISA namespace ArmISA
{ {
typedef const Addr FaultVect; typedef const Addr FaultOffset;
class ArmFault : public FaultBase class ArmFaultBase : public FaultBase
{ {
protected: protected:
virtual bool skipFaultingInstruction() {return false;} Addr getVector(ThreadContext *tc);
virtual bool setRestartAddress() {return true;}
public: public:
Addr BadVAddr; struct FaultVals
Addr EntryHi_Asid; {
Addr EntryHi_VPN2; const FaultName name;
Addr EntryHi_VPN2X; const FaultOffset offset;
Addr Context_BadVPN2; const OperatingMode nextMode;
const uint8_t armPcOffset;
const uint8_t thumbPcOffset;
const bool abortDisable;
const bool fiqDisable;
FaultStat count;
};
#if FULL_SYSTEM #if FULL_SYSTEM
void invoke(ThreadContext * tc) {}; void invoke(ThreadContext *tc);
void setExceptionState(ThreadContext *,uint8_t);
void setHandlerPC(Addr,ThreadContext *);
#endif #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 template<typename T>
{ class ArmFault : public ArmFaultBase
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
{ {
protected: protected:
bool skipFaultingInstruction() {return true;} static FaultVals vals;
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const { return vals.name; }
FaultVect vect() {return _vect;} FaultStat & countStat() {return vals.count;}
FaultStat & countStat() {return _count;} FaultOffset offset() { return vals.offset; }
#if FULL_SYSTEM OperatingMode nextMode() { return vals.nextMode; }
void invoke(ThreadContext * tc); uint8_t armPcOffset() { return vals.armPcOffset; }
#endif 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 class Reset : public ArmFault<Reset> {};
void invoke(ThreadContext * tc); class UndefinedInstruction : public ArmFault<UndefinedInstruction> {};
#endif 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 } // ArmISA namespace

View file

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

View file

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

View file

@ -74,6 +74,56 @@ class ArmStaticInst : public StaticInst
void printDataInst(std::ostream &os, bool withImm) const; void printDataInst(std::ostream &os, bool withImm) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/ */
/* #include "arch/arm/interrupts.hh"
* AST.C
* ArmISA::Interrupts *
* Description: See AST.hh ArmInterruptsParams::create()
* {
* $Id$ return new ArmISA::Interrupts(this);
* }
*/
#include "mem/slicc/ast/AST.hh"

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/ */
/* #ifndef __ARCH_ARM_INTERRUPT_HH__
* LiteralExprAST.hh #define __ARCH_ARM_INTERRUPT_HH__
*
* Description:
*
* $Id: LiteralExprAST.hh,v 3.1 2001/12/12 01:00:20 milo Exp $
*
*/
#ifndef LITERALEXPRAST_H #include "arch/arm/faults.hh"
#define LITERALEXPRAST_H #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" namespace ArmISA
#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)
{ {
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: protected:
MiscReg miscRegs[NumMiscRegs]; 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: public:
void clear() void clear()
@ -52,6 +84,15 @@ namespace ArmISA
CPSR cpsr = 0; CPSR cpsr = 0;
cpsr.mode = MODE_USER; cpsr.mode = MODE_USER;
miscRegs[MISCREG_CPSR] = cpsr; 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. //XXX We need to initialize the rest of the state.
} }
@ -59,34 +100,94 @@ namespace ArmISA
readMiscRegNoEffect(int misc_reg) readMiscRegNoEffect(int misc_reg)
{ {
assert(misc_reg < NumMiscRegs); 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]; return miscRegs[misc_reg];
} }
MiscReg MiscReg
readMiscReg(int misc_reg, ThreadContext *tc) readMiscReg(int misc_reg, ThreadContext *tc)
{ {
assert(misc_reg < NumMiscRegs); return readMiscRegNoEffect(misc_reg);
return miscRegs[misc_reg];
} }
void void
setMiscRegNoEffect(int misc_reg, const MiscReg &val) setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{ {
assert(misc_reg < NumMiscRegs); 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; miscRegs[misc_reg] = val;
} }
void void
setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{ {
assert(misc_reg < NumMiscRegs); if (misc_reg == MISCREG_CPSR) {
miscRegs[misc_reg] = val; updateRegMap(val);
}
return setMiscRegNoEffect(misc_reg, val);
} }
int int
flattenIntIndex(int reg) 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 int
@ -95,9 +196,10 @@ namespace ArmISA
return reg; 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() ISA()

View file

@ -38,14 +38,18 @@ def bitfield ENCODING encoding;
def bitfield OPCODE opcode; def bitfield OPCODE opcode;
def bitfield MEDIA_OPCODE mediaOpcode; def bitfield MEDIA_OPCODE mediaOpcode;
def bitfield MEDIA_OPCODE2 mediaOpcode2; def bitfield MEDIA_OPCODE2 mediaOpcode2;
def bitfield USEIMM useImm;
def bitfield OPCODE_24 opcode24; def bitfield OPCODE_24 opcode24;
def bitfield OPCODE_23_20 opcode23_20; def bitfield OPCODE_23_20 opcode23_20;
def bitfield OPCODE_23_21 opcode23_21; def bitfield OPCODE_23_21 opcode23_21;
def bitfield OPCODE_22 opcode22; def bitfield OPCODE_22 opcode22;
def bitfield OPCODE_20 opcode20;
def bitfield OPCODE_19 opcode19; def bitfield OPCODE_19 opcode19;
def bitfield OPCODE_18 opcode18;
def bitfield OPCODE_15_12 opcode15_12; def bitfield OPCODE_15_12 opcode15_12;
def bitfield OPCODE_15 opcode15; def bitfield OPCODE_15 opcode15;
def bitfield MISC_OPCODE miscOpcode; def bitfield MISC_OPCODE miscOpcode;
def bitfield OPC2 opc2;
def bitfield OPCODE_7 opcode7; def bitfield OPCODE_7 opcode7;
def bitfield OPCODE_4 opcode4; def bitfield OPCODE_4 opcode4;

View file

@ -51,20 +51,25 @@ format DataOp {
resTemp = ((uint64_t)Rm)*((uint64_t)Rs); resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
Rd = (uint32_t)(resTemp & 0xffffffff); Rd = (uint32_t)(resTemp & 0xffffffff);
Rn = (uint32_t)(resTemp >> 32); Rn = (uint32_t)(resTemp >> 32);
}}); }}, llbit);
0x5: WarnUnimpl::smlal(); 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({{ 0x6: smull({{
resTemp = ((int64_t)(int32_t)Rm)* resTemp = ((int64_t)(int32_t)Rm)*
((int64_t)(int32_t)Rs); ((int64_t)(int32_t)Rs);
Rd = (int32_t)(resTemp & 0xffffffff); Rd = (int32_t)(resTemp & 0xffffffff);
Rn = (int32_t)(resTemp >> 32); Rn = (int32_t)(resTemp >> 32);
}}); }}, llbit);
0x7: umlal({{ 0x7: umlal({{
resTemp = ((uint64_t)Rm)*((uint64_t)Rs); resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd); resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd);
Rd = (uint32_t)(resTemp & 0xffffffff); Rd = (uint32_t)(resTemp & 0xffffffff);
Rn = (uint32_t)(resTemp >> 32); Rn = (uint32_t)(resTemp >> 32);
}}); }}, llbit);
} }
1: decode PUBWL { 1: decode PUBWL {
0x10: WarnUnimpl::swp(); 0x10: WarnUnimpl::swp();
@ -91,9 +96,9 @@ format DataOp {
0x2: sub({{ Rd = resTemp = Rn - op2; }}, sub); 0x2: sub({{ Rd = resTemp = Rn - op2; }}, sub);
0x3: rsb({{ Rd = resTemp = op2 - Rn; }}, rsb); 0x3: rsb({{ Rd = resTemp = op2 - Rn; }}, rsb);
0x4: add({{ Rd = resTemp = Rn + op2; }}, add); 0x4: add({{ Rd = resTemp = Rn + op2; }}, add);
0x5: adc({{ Rd = resTemp = Rn + op2 + Cpsr<29:>; }}, add); 0x5: adc({{ Rd = resTemp = Rn + op2 + CondCodes<29:>; }}, add);
0x6: sbc({{ Rd = resTemp = Rn - op2 - !Cpsr<29:>; }}, sub); 0x6: sbc({{ Rd = resTemp = Rn - op2 - !CondCodes<29:>; }}, sub);
0x7: rsc({{ Rd = resTemp = op2 - Rn - !Cpsr<29:>; }}, rsb); 0x7: rsc({{ Rd = resTemp = op2 - Rn - !CondCodes<29:>; }}, rsb);
0x8: tst({{ resTemp = Rn & op2; }}); 0x8: tst({{ resTemp = Rn & op2; }});
0x9: teq({{ resTemp = Rn ^ op2; }}); 0x9: teq({{ resTemp = Rn ^ op2; }});
0xa: cmp({{ resTemp = Rn - op2; }}, sub); 0xa: cmp({{ resTemp = Rn - op2; }}, sub);
@ -105,10 +110,37 @@ format DataOp {
} }
1: decode MISC_OPCODE { 1: decode MISC_OPCODE {
0x0: decode OPCODE { 0x0: decode OPCODE {
0x8: WarnUnimpl::mrs_cpsr(); 0x8: PredOp::mrs_cpsr({{
0x9: WarnUnimpl::msr_cpsr(); Rd = (Cpsr | CondCodes) & 0xF8FF03DF;
0xa: WarnUnimpl::mrs_spsr(); }});
0xb: WarnUnimpl::msr_spsr(); 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 { 0x1: decode OPCODE {
0x9: BranchExchange::bx({{ }}); 0x9: BranchExchange::bx({{ }});
@ -129,28 +161,32 @@ format DataOp {
0xb: WarnUnimpl::qdsub(); 0xb: WarnUnimpl::qdsub();
} }
0x8: decode OPCODE { 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(); 0x9: WarnUnimpl::smlalbb();
0xa: WarnUnimpl::smlawb(); 0xa: WarnUnimpl::smlawb();
0xb: WarnUnimpl::smulbb(); 0xb: smulbb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>); }}, none);
} }
0xa: decode OPCODE { 0xa: decode OPCODE {
0x8: WarnUnimpl::smlatb(); 0x8: smlatb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>) + Rd; }}, overflow);
0x9: WarnUnimpl::smulwb(); 0x9: smulwb({{
Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<15:0>), 47, 16);
}}, none);
0xa: WarnUnimpl::smlaltb(); 0xa: WarnUnimpl::smlaltb();
0xb: WarnUnimpl::smultb(); 0xb: smultb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>); }}, none);
} }
0xc: decode OPCODE { 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(); 0x9: WarnUnimpl::smlawt();
0xa: WarnUnimpl::smlalbt(); 0xa: WarnUnimpl::smlalbt();
0xb: WarnUnimpl::smulbt(); 0xb: smulbt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>); }}, none);
} }
0xe: decode OPCODE { 0xe: decode OPCODE {
0x8: WarnUnimpl::smlatt(); 0x8: smlatt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>) + Rd; }}, overflow);
0x9: WarnUnimpl::smulwt(); 0x9: smulwt({{
Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<31:16>), 47, 16);
}}, none);
0xa: WarnUnimpl::smlaltt(); 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); 0x2: subi({{ Rd = resTemp = Rn - rotated_imm; }}, sub);
0x3: rsbi({{ Rd = resTemp = rotated_imm - Rn; }}, rsb); 0x3: rsbi({{ Rd = resTemp = rotated_imm - Rn; }}, rsb);
0x4: addi({{ Rd = resTemp = Rn + rotated_imm; }}, add); 0x4: addi({{ Rd = resTemp = Rn + rotated_imm; }}, add);
0x5: adci({{ Rd = resTemp = Rn + rotated_imm + Cpsr<29:>; }}, add); 0x5: adci({{
0x6: sbci({{ Rd = resTemp = Rn -rotated_imm - !Cpsr<29:>; }}, sub); Rd = resTemp = Rn + rotated_imm + CondCodes<29:>;
0x7: rsci({{ Rd = resTemp = rotated_imm - Rn - !Cpsr<29:>;}}, rsb); }}, 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; }}); 0x8: tsti({{ resTemp = Rn & rotated_imm; }});
0x9: teqi({{ resTemp = Rn ^ rotated_imm; }}); 0x9: teqi({{ resTemp = Rn ^ rotated_imm; }});
0xa: cmpi({{ resTemp = Rn - rotated_imm; }}, sub); 0xa: cmpi({{ resTemp = Rn - rotated_imm; }}, sub);
@ -178,11 +220,27 @@ format DataOp {
} }
1: decode OPCODE { 1: decode OPCODE {
// The following two instructions aren't supposed to be defined // The following two instructions aren't supposed to be defined
0x8: WarnUnimpl::undefined_instruction(); 0x8: DataOp::movw({{ Rd = IMMED_11_0 | (RN << 12) ; }});
0x9: WarnUnimpl::undefined_instruction(); 0x9: decode RN {
0: decode IMM {
0xa: WarnUnimpl::mrs_i_cpsr(); 0: PredImmOp::nop({{ ; }});
0xb: WarnUnimpl::mrs_i_spsr(); 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); 0x2: AddrMode2::addrMode2(Disp, disp);
@ -324,77 +382,79 @@ format DataOp {
} }
} }
0x7: decode OPCODE_24 { 0x7: decode OPCODE_24 {
0: decode CPNUM { 0: decode OPCODE_4 {
// Coprocessor Instructions 0: decode CPNUM {
0x1: decode OPCODE_4 {
format FloatOp { format FloatOp {
// Basic FPA Instructions 0x1: decode OPCODE_23_20 {
0: decode OPCODE_23_20 { 0x0: decode OPCODE_15 {
0x0: decode OPCODE_15 { 0: adf({{ Fd.sf = Fn.sf + Fm.sf; }});
0: adf({{ Fd.sf = Fn.sf + Fm.sf; }}); 1: mvf({{ Fd.sf = Fm.sf; }});
1: mvf({{ Fd.sf = Fm.sf; }}); }
} 0x1: decode OPCODE_15 {
0x1: decode OPCODE_15 { 0: muf({{ Fd.sf = Fn.sf * Fm.sf; }});
0: muf({{ Fd.sf = Fn.sf * Fm.sf; }}); 1: mnf({{ Fd.sf = -Fm.sf; }});
1: mnf({{ Fd.sf = -Fm.sf; }}); }
} 0x2: decode OPCODE_15 {
0x2: decode OPCODE_15 { 0: suf({{ Fd.sf = Fn.sf - Fm.sf; }});
0: suf({{ Fd.sf = Fn.sf - Fm.sf; }}); 1: abs({{ Fd.sf = fabs(Fm.sf); }});
1: abs({{ Fd.sf = fabs(Fm.sf); }}); }
} 0x3: decode OPCODE_15 {
0x3: decode OPCODE_15 { 0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }});
0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }}); 1: rnd({{ Fd.sf = rint(Fm.sf); }});
1: rnd({{ Fd.sf = rint(Fm.sf); }}); }
} 0x4: decode OPCODE_15 {
0x4: decode OPCODE_15 { 0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }});
0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }}); 1: sqt({{ Fd.sf = sqrt(Fm.sf); }});
1: sqt({{ Fd.sf = sqrt(Fm.sf); }}); }
} 0x5: decode OPCODE_15 {
0x5: decode OPCODE_15 { 0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }});
0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }}); 1: log({{ Fd.sf = log10(Fm.sf); }});
1: log({{ Fd.sf = log10(Fm.sf); }}); }
} 0x6: decode OPCODE_15 {
0x6: decode OPCODE_15 { 0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }});
0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }}); 1: lgn({{ Fd.sf = log(Fm.sf); }});
1: lgn({{ Fd.sf = log(Fm.sf); }}); }
} 0x7: decode OPCODE_15 {
0x7: decode OPCODE_15 { 0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }});
0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }}); 1: exp({{ Fd.sf = exp(Fm.sf); }});
1: exp({{ Fd.sf = exp(Fm.sf); }}); }
} 0x8: decode OPCODE_15 {
0x8: decode OPCODE_15 { 0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }});
0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }}); 1: sin({{ Fd.sf = sin(Fm.sf); }});
1: sin({{ Fd.sf = sin(Fm.sf); }}); }
} 0x9: decode OPCODE_15 {
0x9: decode OPCODE_15 { 0: fml({{ Fd.sf = Fn.sf * Fm.sf; }});
0: fml({{ Fd.sf = Fn.sf * Fm.sf; }}); 1: cos({{ Fd.sf = cos(Fm.sf); }});
1: cos({{ Fd.sf = cos(Fm.sf); }}); }
} 0xa: decode OPCODE_15 {
0xa: decode OPCODE_15 { 0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }});
0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }}); 1: tan({{ Fd.sf = tan(Fm.sf); }});
1: tan({{ Fd.sf = tan(Fm.sf); }}); }
} 0xb: decode OPCODE_15 {
0xb: decode OPCODE_15 { 0: frd({{ Fd.sf = Fm.sf / Fn.sf; }});
0: frd({{ Fd.sf = Fm.sf / Fn.sf; }}); 1: asn({{ Fd.sf = asin(Fm.sf); }});
1: asn({{ Fd.sf = asin(Fm.sf); }}); }
} 0xc: decode OPCODE_15 {
0xc: decode OPCODE_15 { 0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }});
0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }}); 1: acs({{ Fd.sf = acos(Fm.sf); }});
1: acs({{ Fd.sf = acos(Fm.sf); }}); }
} 0xd: decode OPCODE_15 {
0xd: decode OPCODE_15 { 1: atn({{ Fd.sf = atan(Fm.sf); }});
1: atn({{ Fd.sf = atan(Fm.sf); }}); }
} 0xe: decode OPCODE_15 {
0xe: decode OPCODE_15 { // Unnormalised Round
// Unnormalised Round 1: FailUnimpl::urd();
1: FailUnimpl::urd(); }
} 0xf: decode OPCODE_15 {
0xf: decode OPCODE_15 { // Normalise
// Normalise 1: FailUnimpl::nrm();
1: FailUnimpl::nrm(); }
} } // OPCODE_23_20
} } // format FloatOp
1: decode OPCODE_15_12 { } // CPNUM
1: decode CPNUM { // 27-24=1110,4 ==1
1: decode OPCODE_15_12 {
format FloatOp {
0xf: decode OPCODE_23_21 { 0xf: decode OPCODE_23_21 {
format FloatCmp { format FloatCmp {
0x4: cmf({{ Fn.df }}, {{ Fm.df }}); 0x4: cmf({{ Fn.df }}, {{ Fm.df }});
@ -417,36 +477,86 @@ format DataOp {
0x4: FailUnimpl::wfc(); 0x4: FailUnimpl::wfc();
0x5: FailUnimpl::rfc(); 0x5: FailUnimpl::rfc();
} }
} } // format FloatOp
} }
} 0xa: decode MISC_OPCODE {
0xa: decode MISC_OPCODE { 0x1: decode MEDIA_OPCODE {
0x1: decode MEDIA_OPCODE { 0xf: decode RN {
0xf: decode RN { 0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }});
0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }}); 0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }});
0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }}); 0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }});
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 { } // RN
0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }}); } // CPNUM (OP4 == 1)
0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }}); } //OPCODE_4
0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }});
} #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 { #endif // FULL_SYSTEM
// ARM System Call (SoftWare Interrupt) } // OPCODE_24
1: swi({{ if (testPredicate(Cpsr, condCode))
{
if (IMMED_23_0)
xc->syscall(IMMED_23_0);
else
xc->syscall(R7);
}
}});
}
}
} }
} }

View file

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

View file

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

View file

@ -72,6 +72,18 @@ let {{
'predicate_test': predicateTest}, 'predicate_test': predicateTest},
['IsMicroop']) ['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', microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
'MicroMemOp', 'MicroMemOp',
{'memacc_code': 'Mem = Ra;', {'memacc_code': 'Mem = Ra;',
@ -80,14 +92,19 @@ let {{
['IsMicroop']) ['IsMicroop'])
header_output = MicroMemDeclare.subst(microLdrUopIop) + \ header_output = MicroMemDeclare.subst(microLdrUopIop) + \
MicroMemDeclare.subst(microLdrRetUopIop) + \
MicroMemDeclare.subst(microStrUopIop) MicroMemDeclare.subst(microStrUopIop)
decoder_output = MicroConstructor.subst(microLdrUopIop) + \ decoder_output = MicroConstructor.subst(microLdrUopIop) + \
MicroConstructor.subst(microLdrRetUopIop) + \
MicroConstructor.subst(microStrUopIop) MicroConstructor.subst(microStrUopIop)
exec_output = LoadExecute.subst(microLdrUopIop) + \ exec_output = LoadExecute.subst(microLdrUopIop) + \
LoadExecute.subst(microLdrRetUopIop) + \
StoreExecute.subst(microStrUopIop) + \ StoreExecute.subst(microStrUopIop) + \
LoadInitiateAcc.subst(microLdrUopIop) + \ LoadInitiateAcc.subst(microLdrUopIop) + \
LoadInitiateAcc.subst(microLdrRetUopIop) + \
StoreInitiateAcc.subst(microStrUopIop) + \ StoreInitiateAcc.subst(microStrUopIop) + \
LoadCompleteAcc.subst(microLdrUopIop) + \ LoadCompleteAcc.subst(microLdrUopIop) + \
LoadCompleteAcc.subst(microLdrRetUopIop) + \
StoreCompleteAcc.subst(microStrUopIop) 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) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{ {
%(constructor)s; %(constructor)s;
uint32_t regs_to_handle = reglist; uint32_t regs = reglist;
uint32_t start_addr = 0; uint32_t addr = 0;
bool up = machInst.puswl.up;
switch (puswl) if (!up)
{ addr = (ones << 2) - 4;
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;
}
// 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. // 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; unsigned reg = 0;
for (int i = 1; i < ones+1; i++) { bool force_user = machInst.puswl.psruser & !OPCODE_15;
// Get next available bit for transfer bool exception_ret = machInst.puswl.psruser & OPCODE_15;
while (! ( regs_to_handle & (1<<j)))
j++;
regs_to_handle &= ~(1<<j);
if (loadop) for (int i = 1; i < ones + 1; i++) {
microOps[i] = new MicroLdrUop(machInst, j, 17, start_addr); // Find the next register.
else while (!bits(regs, reg))
microOps[i] = new MicroStrUop(machInst, j, 17, start_addr); 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) if (up)
start_addr += 4; addr += 4;
else else
start_addr -= 4; addr -= 4;
} }
if (writeback) { StaticInstPtr &lastUop = microOps[numMicroops - 1];
if (machInst.puswl.writeback) {
if (up) { if (up) {
microOps[numMicroops-1] = lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
new MicroAddiUop(machInst, RN, RN, ones * 4);
} else { } else {
microOps[numMicroops-1] = lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
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 (writeback)
{ {
if (up) { if (up) {
microOps[numMicroops-1] = microOps[numMicroops - 1] =
new MicroAddiUop(machInst, RN, RN, disp8); new MicroAddiUop(machInst, RN, RN, disp8);
} else { } else {
microOps[numMicroops-1] = microOps[numMicroops - 1] =
new MicroSubiUop(machInst, RN, RN, disp8); 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 (writeback) {
if (up) { if (up) {
microOps[numMicroops-1] = microOps[numMicroops - 1] =
new MicroAddiUop(machInst, RN, RN, disp8); new MicroAddiUop(machInst, RN, RN, disp8);
} else { } else {
microOps[numMicroops-1] = microOps[numMicroops - 1] =
new MicroSubiUop(machInst, RN, RN, disp8); new MicroSubiUop(machInst, RN, RN, disp8);
} }
} }
microOps[numMicroops-1]->setLastMicroop(); microOps[numMicroops - 1]->setLastMicroop();
} }
}}; }};

View file

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

View file

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

View file

@ -74,7 +74,7 @@ output exec {{
{ {
panic("attempt to execute unknown instruction " panic("attempt to execute unknown instruction "
"(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst)); "(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 # Generic substitutions for Arm instructions
def ArmGenericCodeSubs(code): def ArmGenericCodeSubs(code):
# Substitute in the shifted portion of operations # 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_Imm',
new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code) '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 return new_code
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 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), 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite),
'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite), 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite),
'R7': ('IntReg', 'uw', '7', 'IsInteger', 5), 'R7': ('IntReg', 'uw', '7', 'IsInteger', 5),
'R0': ('IntReg', 'uw', '0', 'IsInteger', 0),
#Destination register for load/store double instructions #Destination register for load/store double instructions
'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite), 'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite),
'Rde': ('IntReg', 'uw', '(RD | 1)', 'IsInteger', 5, maybePCRead, maybePCWrite), 'Rde': ('IntReg', 'uw', '(RD | 1)', 'IsInteger', 5, maybePCRead, maybePCWrite),
'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 6), 'Rhi': ('IntReg', 'uw', 'INTREG_RHI', 'IsInteger', 7),
'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 7), 'Rlo': ('IntReg', 'uw', 'INTREG_RLO', 'IsInteger', 8),
'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 8), 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 9),
'LR': ('IntReg', 'uw', '14', 'IsInteger', 9), 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', 'IsInteger', 10),
#Register fields for microops #Register fields for microops
'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 11, maybePCRead, maybePCWrite), 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 11, maybePCRead, maybePCWrite),
@ -80,12 +81,13 @@ def operands {{
#Memory Operand #Memory Operand
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 30), 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 30),
'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', 'IsInteger', 40), 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 40),
'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', 'IsInteger', 41), 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', (None, None, 'IsControl'), 41),
'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', 'IsInteger', 42), 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', (None, None, 'IsControl'), 42),
'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', 'IsInteger', 43), 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', (None, None, 'IsControl'), 43),
'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', 'IsInteger', 44), 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', (None, None, 'IsControl'), 44),
'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 45), 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', (None, None, 'IsControl'), 45),
'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 46) '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 WordBytes = 4;
const int HalfwordBytes = 2; const int HalfwordBytes = 2;
const int ByteBytes = 1; const int ByteBytes = 1;
const uint32_t HighVecs = 0xFFFF0000;
}; };
using namespace ArmISA; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/ */
/* #ifndef __ARCH_ARM_KERNEL_STATS_HH__
* TypeAST.C #define __ARCH_ARM_KERNEL_STATS_HH__
*
* Description: See TypeAST.hh
*
* $Id: TypeAST.C,v 3.1 2003/03/22 15:15:16 xu Exp $
*
*/
#include "mem/slicc/ast/TypeAST.hh" #include <map>
#include <stack>
#include <string>
#include <vector>
TypeAST::TypeAST(string* ident_ptr) #include "kern/kernel_stats.hh"
: AST()
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() } /* end namespace ArmISA::Kernel */
{ } /* end namespace ArmISA */
delete m_ident_ptr;
} #endif // __ARCH_ARM_KERNEL_STATS_HH__
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
}

View file

@ -86,6 +86,7 @@ class ArmLinux : public Linux
static const unsigned TIOCISATTY_ = 0x2000745e; static const unsigned TIOCISATTY_ = 0x2000745e;
static const unsigned TIOCGETS_ = 0x402c7413; static const unsigned TIOCGETS_ = 0x402c7413;
static const unsigned TIOCGETA_ = 0x40127417; static const unsigned TIOCGETA_ = 0x40127417;
static const unsigned TCSETAW_ = 0x5407; // 2.6.15 kernel
//@} //@}
/// For table(). /// For table().
@ -147,6 +148,21 @@ class ArmLinux : public Linux
uint64_t st_ino; uint64_t st_ino;
} tgt_stat64; } 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, unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) 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->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu"); strcpy(name->nodename, "m5.eecs.umich.edu");
@ -179,7 +180,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 113 */ SyscallDesc("vm86", unimplementedFunc), /* 113 */ SyscallDesc("vm86", unimplementedFunc),
/* 114 */ SyscallDesc("wait4", unimplementedFunc), /* 114 */ SyscallDesc("wait4", unimplementedFunc),
/* 115 */ SyscallDesc("swapoff", unimplementedFunc), /* 115 */ SyscallDesc("swapoff", unimplementedFunc),
/* 116 */ SyscallDesc("sysinfo", unimplementedFunc), /* 116 */ SyscallDesc("sysinfo", sysinfoFunc<ArmLinux>),
/* 117 */ SyscallDesc("ipc", unimplementedFunc), /* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc), /* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc), /* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
@ -417,7 +418,8 @@ static SyscallReturn
setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process, setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) 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, tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0,
(uint8_t *)&tlsPtr, sizeof(tlsPtr)); (uint8_t *)&tlsPtr, sizeof(tlsPtr));
@ -511,12 +513,12 @@ ArmLinuxProcess::startup()
} }
ArmISA::IntReg 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. // Linux apparently allows more parameter than the ABI says it should.
// This limit may need to be increased even further. // This limit may need to be increased even further.
assert(i < 6); assert(i < 6);
return tc->readIntReg(ArgumentReg0 + i); return tc->readIntReg(ArgumentReg0 + i++);
} }
void void

View file

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

View file

@ -55,23 +55,24 @@ namespace ArmISA
enum MiscRegIndex { enum MiscRegIndex {
MISCREG_CPSR = 0, MISCREG_CPSR = 0,
MISCREG_SPSR, MISCREG_SPSR,
MISCREG_SPSR_FIQ, MISCREG_SPSR_FIQ,
MISCREG_SPSR_IRQ, MISCREG_SPSR_IRQ,
MISCREG_SPSR_SVC, MISCREG_SPSR_SVC,
MISCREG_SPSR_MON,
MISCREG_SPSR_UND, MISCREG_SPSR_UND,
MISCREG_SPSR_ABT, MISCREG_SPSR_ABT,
MISCREG_FPSR, MISCREG_FPSR,
MISCREG_FPSID, MISCREG_FPSID,
MISCREG_FPSCR, MISCREG_FPSCR,
MISCREG_FPEXC, MISCREG_FPEXC,
NUM_MISCREGS MISCREG_SCTLR,
NUM_MISCREGS
}; };
const char * const miscRegName[NUM_MISCREGS] = { const char * const miscRegName[NUM_MISCREGS] = {
"cpsr", "cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und",
"spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und", "spsr_abt", "spsr_abt", "fpsr", "fpsid", "fpscr", "fpexc", "sctlr"
"fpsr"
}; };
BitUnion32(CPSR) BitUnion32(CPSR)
@ -80,8 +81,10 @@ namespace ArmISA
Bitfield<29> c; Bitfield<29> c;
Bitfield<28> v; Bitfield<28> v;
Bitfield<27> q; Bitfield<27> q;
Bitfield<26,25> it1;
Bitfield<24> j; Bitfield<24> j;
Bitfield<19, 16> ge; Bitfield<19, 16> ge;
Bitfield<15,10> it2;
Bitfield<9> e; Bitfield<9> e;
Bitfield<8> a; Bitfield<8> a;
Bitfield<7> i; Bitfield<7> i;
@ -89,6 +92,35 @@ namespace ArmISA
Bitfield<5> t; Bitfield<5> t;
Bitfield<4, 0> mode; Bitfield<4, 0> mode;
EndBitUnion(CPSR) 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__ #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]); changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]);
//CPSR //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]); changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]);
} }

View file

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

View file

@ -53,7 +53,7 @@ class ArmLiveProcess : public LiveProcess
public: public:
void argsInit(int intSize, int pageSize); 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 setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
}; };

View file

@ -32,6 +32,7 @@
#define __ARCH_ARM_REGISTERS_HH__ #define __ARCH_ARM_REGISTERS_HH__
#include "arch/arm/max_inst_regs.hh" #include "arch/arm/max_inst_regs.hh"
#include "arch/arm/intregs.hh"
#include "arch/arm/miscregs.hh" #include "arch/arm/miscregs.hh"
namespace ArmISA { namespace ArmISA {
@ -51,13 +52,11 @@ typedef float FloatReg;
typedef uint64_t MiscReg; typedef uint64_t MiscReg;
// Constants Related to the number of registers // Constants Related to the number of registers
const int NumIntArchRegs = 16; const int NumIntArchRegs = NUM_ARCH_INTREGS;
const int NumIntSpecialRegs = 19;
const int NumFloatArchRegs = 16; const int NumFloatArchRegs = 16;
const int NumFloatSpecialRegs = 5; 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 NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;
const int NumMiscRegs = NUM_MISCREGS; const int NumMiscRegs = NUM_MISCREGS;
@ -72,12 +71,11 @@ const int ArgumentReg1 = 1;
const int ArgumentReg2 = 2; const int ArgumentReg2 = 2;
const int ArgumentReg3 = 3; const int ArgumentReg3 = 3;
const int FramePointerReg = 11; const int FramePointerReg = 11;
const int StackPointerReg = 13; const int StackPointerReg = INTREG_SP;
const int ReturnAddressReg = 14; const int ReturnAddressReg = INTREG_LR;
const int PCReg = 15; const int PCReg = INTREG_PC;
const int ZeroReg = NumIntArchRegs; const int ZeroReg = INTREG_ZERO;
const int AddrReg = ZeroReg + 1; // Used to generate address for uops
const int SyscallNumReg = ReturnValueReg; const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ReturnValueReg; const int SyscallPseudoReturnReg = ReturnValueReg;
@ -116,35 +114,6 @@ enum FCSRFields {
Cause_Field = 11 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 } // namespace ArmISA
#endif #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) 2005 The Regents of The University of Michigan
* Copyright (c) 2007-2008 The Florida State University
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Authors: Ali Saidi * Authors: Nathan Binkert
* Stephen Hines
*/ */
#ifndef __ARCH_ARM_STACKTRACE_HH__ #ifndef __ARCH_ARM_STACKTRACE_HH__
@ -37,11 +35,11 @@
#include "cpu/static_inst.hh" #include "cpu/static_inst.hh"
class ThreadContext; class ThreadContext;
class StackTrace;
namespace ArmISA namespace ArmISA
{ {
class StackTrace;
class ProcessInfo class ProcessInfo
{ {
private: private:
@ -64,7 +62,7 @@ class ProcessInfo
class StackTrace class StackTrace
{ {
protected: protected:
typedef TheISA::MachInst MachInst; typedef ArmISA::MachInst MachInst;
private: private:
ThreadContext *tc; ThreadContext *tc;
std::vector<Addr> stack; std::vector<Addr> stack;
@ -94,10 +92,6 @@ class StackTrace
public: public:
const std::vector<Addr> &getstack() const { return stack; } 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 #if TRACING_ON
private: private:
void dump(); void dump();
@ -123,6 +117,6 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
return true; return true;
} }
} } // Namespace ArmISA
#endif // __ARCH_ARM_STACKTRACE_HH__ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/ */
/* #include "arch/arm/system.hh"
* TypeFieldAST.C
*
* Description: See TypeFieldAST.hh
*
* $Id$
*
*/
#include "mem/slicc/ast/TypeFieldAST.hh"
TypeFieldAST::TypeFieldAST(PairListAST* pairs_ptr) using namespace LittleEndianGuest;
: AST(pairs_ptr->getPairs()) {
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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/ */
/* #ifndef __ARCH_ARM_SYSTEM_HH__
* StatementAST.C #define __ARCH_ARM_SYSTEM_HH__
*
* Description: See StatementAST.hh
*
* $Id$
*
*/
#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() #endif
{
indentation_depth--;
}
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; return NoFault;
#else #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 #endif
} }

View file

@ -45,16 +45,20 @@ namespace ArmISA
// All the different types of opcode fields. // All the different types of opcode fields.
Bitfield<27, 25> encoding; Bitfield<27, 25> encoding;
Bitfield<25> useImm;
Bitfield<24, 21> opcode; Bitfield<24, 21> opcode;
Bitfield<24, 20> mediaOpcode; Bitfield<24, 20> mediaOpcode;
Bitfield<24> opcode24; Bitfield<24> opcode24;
Bitfield<23, 20> opcode23_20; Bitfield<23, 20> opcode23_20;
Bitfield<23, 21> opcode23_21; Bitfield<23, 21> opcode23_21;
Bitfield<20> opcode20;
Bitfield<22> opcode22; Bitfield<22> opcode22;
Bitfield<19> opcode19; Bitfield<19> opcode19;
Bitfield<18> opcode18;
Bitfield<15, 12> opcode15_12; Bitfield<15, 12> opcode15_12;
Bitfield<15> opcode15; Bitfield<15> opcode15;
Bitfield<7, 4> miscOpcode; Bitfield<7, 4> miscOpcode;
Bitfield<7,5> opc2;
Bitfield<7> opcode7; Bitfield<7> opcode7;
Bitfield<4> opcode4; Bitfield<4> opcode4;
@ -156,6 +160,7 @@ namespace ArmISA
MODE_FIQ = 17, MODE_FIQ = 17,
MODE_IRQ = 18, MODE_IRQ = 18,
MODE_SVC = 19, MODE_SVC = 19,
MODE_MON = 22,
MODE_ABORT = 23, MODE_ABORT = 23,
MODE_UNDEFINED = 27, MODE_UNDEFINED = 27,
MODE_SYSTEM = 31 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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() uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
{ #if FULL_SYSTEM
delete m_expr_ptr; 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(); return new UnimpFault(csprintf("MCR CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n",
Type* actual_type_ptr = m_expr_ptr->generate(code); CRn, opc1, CRm, opc2));
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() + "'");
}
} }
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"); 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 # get type names
from types import * 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 lex
from ply import yacc from ply import yacc

View file

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

View file

@ -29,12 +29,13 @@
# Authors: Jaidev Patwardhan # Authors: Jaidev Patwardhan
# Korey Sewell # Korey Sewell
from m5.SimObject import SimObject from m5.defines import buildEnv
from m5.params import * from m5.params import *
from BaseCPU import BaseCPU from BaseCPU import BaseCPU
class BaseMipsCPU(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_IPTI = Param.Unsigned(0,"No Description")
CP0_IntCtl_IPPCI = Param.Unsigned(0,"No Description") CP0_IntCtl_IPPCI = Param.Unsigned(0,"No Description")
CP0_SrsCtl_HSS = Param.Unsigned(0,"No Description") CP0_SrsCtl_HSS = Param.Unsigned(0,"No Description")

View file

@ -28,10 +28,10 @@
# #
# Authors: Jaidev Patwardhan # Authors: Jaidev Patwardhan
from m5.SimObject import SimObject from m5.defines import buildEnv
from m5.params import * from m5.params import *
from m5.proxy import * from m5.proxy import *
from m5 import build_env
from System import System from System import System
class MipsSystem(System): class MipsSystem(System):
@ -42,7 +42,7 @@ class MipsSystem(System):
system_type = Param.UInt64("Type of system we are emulating") system_type = Param.UInt64("Type of system we are emulating")
system_rev = Param.UInt64("Revision 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): class LinuxMipsSystem(MipsSystem):
type = 'LinuxMipsSystem' type = 'LinuxMipsSystem'
system_type = 34 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 b_values[SIMD_MAX_VALS];
uint64_t c_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(a, a_values, SIMD_FMT_PH, SIGNED);
simdUnpack(b, b_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]; int nvals = SIMD_NVALS[fmt];
uint64_t a_values[SIMD_MAX_VALS]; uint64_t a_values[SIMD_MAX_VALS];
uint64_t b_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; uint32_t ouflag = 0;
simdUnpack(a, a_values, fmt, SIGNED); simdUnpack(a, a_values, fmt, SIGNED);

View file

@ -172,8 +172,11 @@ namespace MipsISA
return reg; 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)
{}
}; };
} }

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; }}, def format Prefetch(ea_code = {{ EA = Rs + disp; }},
mem_flags = [], pf_flags = [], inst_flags = []) {{ 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', pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
'IsDataPrefetch', 'MemReadOp'] 'IsDataPrefetch', 'MemReadOp']

View file

@ -100,6 +100,7 @@ class MipsLinux : public Linux
static const unsigned TIOCISATTY_ = 0x5480; static const unsigned TIOCISATTY_ = 0x5480;
static const unsigned TIOCGETS_ = 0x540d; static const unsigned TIOCGETS_ = 0x540d;
static const unsigned TIOCGETA_ = 0x7417; static const unsigned TIOCGETA_ = 0x7417;
static const unsigned TCSETAW_ = 0x5403; // 2.6.15 kernel
//@} //@}
/// For table(). /// For table().
@ -126,6 +127,22 @@ class MipsLinux : public Linux
/// assign themselves to process IDs reserved for /// assign themselves to process IDs reserved for
/// the root users. /// the root users.
static const int NUM_ROOT_PROCS = 2; 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 #endif

View file

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

View file

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

View file

@ -32,9 +32,15 @@
#include "arch/mips/isa_traits.hh" #include "arch/mips/isa_traits.hh"
#include "arch/mips/process.hh" #include "arch/mips/process.hh"
#include "base/loader/object_file.hh" #include "base/loader/object_file.hh"
#include "base/misc.hh" #include "base/misc.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/system.hh" #include "sim/system.hh"
using namespace std; using namespace std;
@ -62,14 +68,89 @@ MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params,
void void
MipsLiveProcess::startup() MipsLiveProcess::startup()
{ {
Process::startup();
argsInit(MachineBytes, VMPageSize); 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 MipsISA::IntReg
MipsLiveProcess::getSyscallArg(ThreadContext *tc, int i) MipsLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
{ {
assert(i < 6); assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i); return tc->readIntReg(FirstArgumentReg + i++);
} }
void void

View file

@ -45,10 +45,12 @@ class MipsLiveProcess : public LiveProcess
protected: protected:
MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile); MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
virtual void startup(); void startup();
void argsInit(int intSize, int pageSize);
public: 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 setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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; class PowerFault : public FaultBase
m_pairs = pairs; {
if (!existPair("short")) { protected:
addPair("short", m_id); FaultName _name;
}
m_used = false; 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) } // PowerISA namespace
{
m_id = id;
m_location = location;
if (!existPair("short")) {
addPair("short", m_id);
}
m_used = false;
}
const string& Symbol::lookupPair(const string& key) const #endif // __ARCH_POWER_FAULTS_HH__
{
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);
}

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Timothy M. Jones
*/ */
/* #include "arch/power/insts/condition.hh"
* $Id$
*
* */
#include "mem/slicc/symbols/Var.hh" using namespace PowerISA;
#include "mem/slicc/symbols/StateMachine.hh"
Var::Var(string id, const Location& location, std::string
Type* type_ptr, string code, CondLogicOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
const Map<string, string>& pairs,
StateMachine* machine_ptr) : Symbol(id, location, pairs)
{ {
if (machine_ptr == NULL) { std::stringstream ss;
m_c_id = id;
} else {
m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name
}
m_machine_ptr = machine_ptr; ccprintf(ss, "%-10s ", mnemonic);
m_type_ptr = type_ptr;
m_code = code; // 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Timothy M. Jones
*/ */
/* #ifndef __ARCH_POWER_INSTS_CONDITION_HH__
* DeclAST.hh #define __ARCH_POWER_INSTS_CONDITION_HH__
*
* Description: #include "arch/power/insts/static_inst.hh"
* #include "base/cprintf.hh"
* $Id$
* namespace PowerISA
{
/**
* Class for condition register logical operations.
*/ */
class CondLogicOp : public PowerStaticInst
{
protected:
#ifndef DECLAST_H uint32_t ba;
#define DECLAST_H uint32_t bb;
uint32_t bt;
#include "mem/slicc/slicc_global.hh" /// Constructor
#include "mem/slicc/ast/AST.hh" CondLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
#include "mem/slicc/ast/PairListAST.hh" : PowerStaticInst(mnem, _machInst, __opClass),
#include "mem/slicc/symbols/StateMachine.hh" ba(machInst.ba),
#include "mem/slicc/ast/TypeAST.hh" bb(machInst.bb),
bt(machInst.bt)
{
}
class DeclAST : public AST { std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
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)
}; };
// Output operator declaration /**
ostream& operator<<(ostream& out, const DeclAST& obj); * Class for condition register move operations.
*/
// ******************* Definitions ******************* class CondMoveOp : public PowerStaticInst
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const DeclAST& obj)
{ {
obj.print(out); protected:
out << flush;
return out;
}
#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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Timothy M. Jones
*/ */
/* #include "arch/power/insts/mem.hh"
* DeclListAST.C #include "base/loader/symtab.hh"
*
* Description: See DeclListAST.hh
*
* $Id$
*
*/
#include "mem/slicc/ast/DeclListAST.hh" using namespace PowerISA;
DeclListAST::DeclListAST(Vector<DeclAST*>* vec_ptr) std::string
: AST() MemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{ {
assert(vec_ptr != NULL); return csprintf("%-10s", mnemonic);
m_vec_ptr = vec_ptr;
} }
// Singleton constructor. std::string
DeclListAST::DeclListAST(DeclAST* Decl_ptr) MemDispOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
: AST()
{ {
assert(Decl_ptr != NULL); std::stringstream ss;
m_vec_ptr = new Vector<DeclAST*>;
m_vec_ptr->insertAtTop(Decl_ptr);
}
DeclListAST::~DeclListAST() ccprintf(ss, "%-10s ", mnemonic);
{
int size = m_vec_ptr->size();
for(int i=0; i<size; i++) {
delete (*m_vec_ptr)[i];
}
delete m_vec_ptr;
}
void DeclListAST::generate() const // Print the destination only for a load
{ if (!flags[IsStore]) {
int size = m_vec_ptr->size(); if (_numDestRegs > 0) {
for(int i=0; i<size; i++) {
(*m_vec_ptr)[i]->generate();
}
}
void DeclListAST::findMachines() const // If the instruction updates the source register with the
{ // EA, then this source register is placed in position 0,
int size = m_vec_ptr->size(); // therefore we print the last destination register.
for(int i=0; i<size; i++) { printReg(ss, _destRegIdx[_numDestRegs-1]);
(*m_vec_ptr)[i]->findMachines(); }
} }
}
void DeclListAST::print(ostream& out) const // Print the data register for a store
{ else {
assert(m_vec_ptr != NULL); printReg(ss, _srcRegIdx[1]);
out << "[DeclListAST: " << *m_vec_ptr << "]"; }
// 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Timothy M. Jones
*/ */
/* #ifndef __ARCH_POWER_MEM_HH__
* TypeDeclAST.C #define __ARCH_POWER_MEM_HH__
*
* Description: See TypeDeclAST.hh #include "arch/power/insts/static_inst.hh"
*
* $Id: TypeDeclAST.C,v 3.1 2003/03/22 15:15:17 xu Exp $ namespace PowerISA
* {
/**
* Base class for memory operations.
*/ */
class MemOp : public PowerStaticInst
#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)
{ {
m_type_ast_ptr = type_ast_ptr; protected:
m_field_vec_ptr = field_vec_ptr;
}
TypeDeclAST::~TypeDeclAST() /// Memory request flags. See mem_req_base.hh.
{ unsigned memAccessFlags;
delete m_type_ast_ptr; /// Pointer to EAComp object.
if (m_field_vec_ptr != NULL) { const StaticInstPtr eaCompPtr;
int size = m_field_vec_ptr->size(); /// Pointer to MemAcc object.
for(int i=0; i<size; i++) { const StaticInstPtr memAccPtr;
delete (*m_field_vec_ptr)[i];
/// 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; protected:
string id = m_type_ast_ptr->toString();
// Make the new type int16_t disp;
Type* new_type_ptr = new Type(id, getLocation(), getPairs(),
g_sym_table.getStateMachine());
g_sym_table.newSym(new_type_ptr);
// Add all of the fields of the type to it /// Constructor
if (m_field_vec_ptr != NULL) { MemDispOp(const char *mnem, MachInst _machInst, OpClass __opClass,
int size = m_field_vec_ptr->size(); StaticInstPtr _eaCompPtr = nullStaticInstPtr,
for(int i=0; i<size; i++) { StaticInstPtr _memAccPtr = nullStaticInstPtr)
(*m_field_vec_ptr)[i]->generate(new_type_ptr); : MemOp(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
disp(machInst.d)
{
} }
}
}
void TypeDeclAST::print(ostream& out) const std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
{ };
out << "[TypeDecl: " << m_type_ast_ptr->toString() << "]";
} } // 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Timothy M. Jones
*/ */
/* #ifndef __ARCH_POWER_INSTS_MISC_HH__
* LiteralExprAST.C #define __ARCH_POWER_INSTS_MISC_HH__
*
* Description: See LiteralExprAST.hh
*
* $Id: LiteralExprAST.C,v 3.1 2002/10/22 21:27:52 milo Exp $
*
*/
#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) { * Class for misc operations.
// Can't find the type */
error("Internal: can't primitive type '" + m_type + "'"); class MiscOp : public PowerStaticInst
} {
return type_ptr; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Timothy M. Jones
*/ */
/* #ifndef __ARCH_POWER_INSTS_STATICINST_HH__
* PairListAST.hh #define __ARCH_POWER_INSTS_STATICINST_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef PairListAST_H #include "base/trace.hh"
#define PairListAST_H #include "cpu/static_inst.hh"
#include "mem/slicc/slicc_global.hh" namespace PowerISA
#include "mem/slicc/ast/AST.hh" {
#include "mem/slicc/ast/PairAST.hh"
class PowerStaticInst : public StaticInst
{
protected:
class PairListAST : public AST { // Constructor
public: PowerStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
// Constructors : StaticInst(mnem, _machInst, __opClass)
PairListAST() : AST() {} {
}
// Destructor // Insert a condition value into a CR (condition register) field
//~PairListAST(); 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 /// Print a register name for disassembly given the unique
void addPair(PairAST* pair_ptr); /// dependence tag number (FP or int).
void print(ostream& out) const; void
private: printReg(std::ostream &os, int reg) const;
// Private Methods
// Private copy constructor and assignment operator std::string
PairListAST(const PairListAST& obj); generateDisassembly(Addr pc, const SymbolTable *symtab) const;
PairListAST& operator=(const PairListAST& obj);
// Data Members (m_ prefix)
}; };
// Output operator declaration } // PowerISA namespace
ostream& operator<<(ostream& out, const PairListAST& obj);
// ******************* Definitions ******************* #endif //__ARCH_POWER_INSTS_STATICINST_HH__
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const PairListAST& obj)
{
obj.print(out);
out << flush;
return out;
}
#endif //PairListAST_H

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