merge
This commit is contained in:
commit
279f179bab
682 changed files with 26213 additions and 20254 deletions
|
@ -7,3 +7,4 @@ cscope.out
|
|||
*.pyc
|
||||
*~
|
||||
.*.swp
|
||||
m5out
|
||||
|
|
92
SConstruct
92
SConstruct
|
@ -96,6 +96,7 @@ For more details, see:
|
|||
"""
|
||||
raise
|
||||
|
||||
# Global Python includes
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
@ -106,55 +107,18 @@ from os.path import abspath, basename, dirname, expanduser, normpath
|
|||
from os.path import exists, isdir, isfile
|
||||
from os.path import join as joinpath, split as splitpath
|
||||
|
||||
# SCons includes
|
||||
import SCons
|
||||
import SCons.Node
|
||||
|
||||
def read_command(cmd, **kwargs):
|
||||
"""run the command cmd, read the results and return them
|
||||
this is sorta like `cmd` in shell"""
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
extra_python_paths = [
|
||||
Dir('src/python').srcnode().abspath, # M5 includes
|
||||
Dir('ext/ply').srcnode().abspath, # ply is used by several files
|
||||
]
|
||||
|
||||
if isinstance(cmd, str):
|
||||
cmd = cmd.split()
|
||||
sys.path[1:1] = extra_python_paths
|
||||
|
||||
no_exception = 'exception' in kwargs
|
||||
exception = kwargs.pop('exception', None)
|
||||
|
||||
kwargs.setdefault('shell', False)
|
||||
kwargs.setdefault('stdout', PIPE)
|
||||
kwargs.setdefault('stderr', STDOUT)
|
||||
kwargs.setdefault('close_fds', True)
|
||||
try:
|
||||
subp = Popen(cmd, **kwargs)
|
||||
except Exception, e:
|
||||
if no_exception:
|
||||
return exception
|
||||
raise
|
||||
|
||||
return subp.communicate()[0]
|
||||
|
||||
# helper function: compare arrays or strings of version numbers.
|
||||
# E.g., compare_version((1,3,25), (1,4,1)')
|
||||
# returns -1, 0, 1 if v1 is <, ==, > v2
|
||||
def compare_versions(v1, v2):
|
||||
def make_version_list(v):
|
||||
if isinstance(v, (list,tuple)):
|
||||
return v
|
||||
elif isinstance(v, str):
|
||||
return map(lambda x: int(re.match('\d+', x).group()), v.split('.'))
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
v1 = make_version_list(v1)
|
||||
v2 = make_version_list(v2)
|
||||
# Compare corresponding elements of lists
|
||||
for n1,n2 in zip(v1, v2):
|
||||
if n1 < n2: return -1
|
||||
if n1 > n2: return 1
|
||||
# all corresponding values are equal... see if one has extra values
|
||||
if len(v1) < len(v2): return -1
|
||||
if len(v1) > len(v2): return 1
|
||||
return 0
|
||||
from m5.util import compareVersions, readCommand
|
||||
|
||||
########################################################################
|
||||
#
|
||||
|
@ -162,7 +126,7 @@ def compare_versions(v1, v2):
|
|||
#
|
||||
########################################################################
|
||||
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
|
||||
'RANLIB' ])
|
||||
'PYTHONPATH', 'RANLIB' ])
|
||||
|
||||
use_env = {}
|
||||
for key,val in os.environ.iteritems():
|
||||
|
@ -173,6 +137,10 @@ main = Environment(ENV=use_env)
|
|||
main.root = Dir(".") # The current directory (where this file lives).
|
||||
main.srcdir = Dir("src") # The source directory
|
||||
|
||||
# add useful python code PYTHONPATH so it can be used by subprocesses
|
||||
# as well
|
||||
main.AppendENVPath('PYTHONPATH', extra_python_paths)
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Mercurial Stuff.
|
||||
|
@ -217,7 +185,7 @@ if hgdir.exists():
|
|||
# 1) Grab repository revision if we know it.
|
||||
cmd = "hg id -n -i -t -b"
|
||||
try:
|
||||
hg_info = read_command(cmd, cwd=main.root.abspath).strip()
|
||||
hg_info = readCommand(cmd, cwd=main.root.abspath).strip()
|
||||
except OSError:
|
||||
print mercurial_bin_not_found
|
||||
|
||||
|
@ -378,11 +346,8 @@ Export('extras_dir_list')
|
|||
# the ext directory should be on the #includes path
|
||||
main.Append(CPPPATH=[Dir('ext')])
|
||||
|
||||
# M5_PLY is used by isa_parser.py to find the PLY package.
|
||||
main.Append(ENV = { 'M5_PLY' : Dir('ext/ply').abspath })
|
||||
|
||||
CXX_version = read_command([main['CXX'],'--version'], exception=False)
|
||||
CXX_V = read_command([main['CXX'],'-V'], exception=False)
|
||||
CXX_version = readCommand([main['CXX'],'--version'], exception=False)
|
||||
CXX_V = readCommand([main['CXX'],'-V'], exception=False)
|
||||
|
||||
main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
|
||||
main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
|
||||
|
@ -426,7 +391,7 @@ if main['BATCH']:
|
|||
|
||||
if sys.platform == 'cygwin':
|
||||
# cygwin has some header file issues...
|
||||
main.Append(CCFLAGS=Split("-Wno-uninitialized"))
|
||||
main.Append(CCFLAGS="-Wno-uninitialized")
|
||||
|
||||
# Check for SWIG
|
||||
if not main.has_key('SWIG'):
|
||||
|
@ -435,7 +400,7 @@ if not main.has_key('SWIG'):
|
|||
Exit(1)
|
||||
|
||||
# Check for appropriate SWIG version
|
||||
swig_version = read_command(('swig', '-version'), exception='').split()
|
||||
swig_version = readCommand(('swig', '-version'), exception='').split()
|
||||
# First 3 words should be "SWIG Version x.y.z"
|
||||
if len(swig_version) < 3 or \
|
||||
swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
|
||||
|
@ -443,7 +408,7 @@ if len(swig_version) < 3 or \
|
|||
Exit(1)
|
||||
|
||||
min_swig_version = '1.3.28'
|
||||
if compare_versions(swig_version[2], min_swig_version) < 0:
|
||||
if compareVersions(swig_version[2], min_swig_version) < 0:
|
||||
print 'Error: SWIG version', min_swig_version, 'or newer required.'
|
||||
print ' Installed version:', swig_version[2]
|
||||
Exit(1)
|
||||
|
@ -514,8 +479,8 @@ conf.CheckLeading()
|
|||
try:
|
||||
import platform
|
||||
uname = platform.uname()
|
||||
if uname[0] == 'Darwin' and compare_versions(uname[2], '9.0.0') >= 0:
|
||||
if int(read_command('sysctl -n hw.cpu64bit_capable')[0]):
|
||||
if uname[0] == 'Darwin' and compareVersions(uname[2], '9.0.0') >= 0:
|
||||
if int(readCommand('sysctl -n hw.cpu64bit_capable')[0]):
|
||||
main.Append(CCFLAGS='-arch x86_64')
|
||||
main.Append(CFLAGS='-arch x86_64')
|
||||
main.Append(LINKFLAGS='-arch x86_64')
|
||||
|
@ -615,9 +580,9 @@ have_mysql = bool(mysql_config)
|
|||
|
||||
# Check MySQL version.
|
||||
if have_mysql:
|
||||
mysql_version = read_command(mysql_config + ' --version')
|
||||
mysql_version = readCommand(mysql_config + ' --version')
|
||||
min_mysql_version = '4.1'
|
||||
if compare_versions(mysql_version, min_mysql_version) < 0:
|
||||
if compareVersions(mysql_version, min_mysql_version) < 0:
|
||||
print 'Warning: MySQL', min_mysql_version, 'or newer required.'
|
||||
print ' Version', mysql_version, 'detected.'
|
||||
have_mysql = False
|
||||
|
@ -777,17 +742,10 @@ def make_switching_dir(dname, switch_headers, env):
|
|||
# list of ISAs from env['ALL_ISA_LIST'].
|
||||
def gen_switch_hdr(target, source, env):
|
||||
fname = str(target[0])
|
||||
bname = basename(fname)
|
||||
f = open(fname, 'w')
|
||||
f.write('#include "arch/isa_specific.hh"\n')
|
||||
cond = '#if'
|
||||
for isa in all_isa_list:
|
||||
f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n'
|
||||
% (cond, isa.upper(), dname, isa, bname))
|
||||
cond = '#elif'
|
||||
f.write('#else\n#error "THE_ISA not set"\n#endif\n')
|
||||
isa = env['TARGET_ISA'].lower()
|
||||
print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
|
||||
f.close()
|
||||
return 0
|
||||
|
||||
# String to print when generating header
|
||||
def gen_switch_hdr_string(target, source, env):
|
||||
|
|
3
build_opts/ARM_FS
Normal file
3
build_opts/ARM_FS
Normal file
|
@ -0,0 +1,3 @@
|
|||
TARGET_ISA = 'arm'
|
||||
CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU'
|
||||
FULL_SYSTEM = 1
|
3
build_opts/POWER_SE
Normal file
3
build_opts/POWER_SE
Normal file
|
@ -0,0 +1,3 @@
|
|||
TARGET_ISA = 'power'
|
||||
FULL_SYSTEM = 0
|
||||
CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU'
|
|
@ -26,7 +26,6 @@
|
|||
#
|
||||
# Authors: Lisa Hsu
|
||||
|
||||
import m5
|
||||
from m5.objects import *
|
||||
|
||||
class L1Cache(BaseCache):
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#
|
||||
# Authors: Kevin Lim
|
||||
|
||||
import m5
|
||||
from m5 import makeList
|
||||
from m5.objects import *
|
||||
from Benchmarks import *
|
||||
|
||||
|
@ -81,6 +79,50 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
|
|||
|
||||
return self
|
||||
|
||||
def makeLinuxAlphaRubySystem(mem_mode, rubymem, mdesc = None):
|
||||
class BaseTsunami(Tsunami):
|
||||
ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0)
|
||||
ide = IdeController(disks=[Parent.disk0, Parent.disk2],
|
||||
pci_func=0, pci_dev=0, pci_bus=0)
|
||||
|
||||
|
||||
self = LinuxAlphaSystem(physmem = rubymem)
|
||||
if not mdesc:
|
||||
# generic system
|
||||
mdesc = SysConfig()
|
||||
self.readfile = mdesc.script()
|
||||
|
||||
# Create pio bus to connect all device pio ports to rubymem's pio port
|
||||
self.piobus = Bus(bus_id=0)
|
||||
|
||||
self.disk0 = CowIdeDisk(driveID='master')
|
||||
self.disk2 = CowIdeDisk(driveID='master')
|
||||
self.disk0.childImage(mdesc.disk())
|
||||
self.disk2.childImage(disk('linux-bigswap2.img'))
|
||||
self.tsunami = BaseTsunami()
|
||||
self.tsunami.attachIO(self.piobus)
|
||||
self.tsunami.ide.pio = self.piobus.port
|
||||
self.tsunami.ethernet.pio = self.piobus.port
|
||||
|
||||
# connect the dma ports directly to ruby dma ports
|
||||
self.tsunami.ide.dma = self.physmem.dma_port
|
||||
self.tsunami.ethernet.dma = self.physmem.dma_port
|
||||
|
||||
# connect the pio bus to rubymem
|
||||
self.physmem.pio_port = self.piobus.port
|
||||
|
||||
self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(),
|
||||
read_only = True))
|
||||
self.intrctrl = IntrControl()
|
||||
self.mem_mode = mem_mode
|
||||
self.terminal = Terminal()
|
||||
self.kernel = binary('vmlinux')
|
||||
self.pal = binary('ts_osfpal')
|
||||
self.console = binary('console')
|
||||
self.boot_osflags = 'root=/dev/hda1 console=ttyS0'
|
||||
|
||||
return self
|
||||
|
||||
def makeSparcSystem(mem_mode, mdesc = None):
|
||||
class CowMmDisk(MmDisk):
|
||||
image = CowDiskImage(child=RawDiskImage(read_only=True),
|
||||
|
|
|
@ -38,6 +38,7 @@ parser.add_option("--fastmem", action="store_true")
|
|||
# Run duration options
|
||||
parser.add_option("-m", "--maxtick", type="int")
|
||||
parser.add_option("--maxtime", type="float")
|
||||
parser.add_option("--maxinsts", type="int")
|
||||
parser.add_option("--prog_intvl", type="int")
|
||||
|
||||
|
||||
|
@ -52,6 +53,9 @@ parser.add_option("--checkpoint-dir", action="store", type="string",
|
|||
help="Place all checkpoints in this absolute directory")
|
||||
parser.add_option("-r", "--checkpoint-restore", action="store", type="int",
|
||||
help="restore from checkpoint <N>")
|
||||
parser.add_option("--checkpoint-at-end", action="store_true",
|
||||
help="take a checkpoint at end of run")
|
||||
|
||||
|
||||
# CPU Switching - default switch model goes from a checkpoint
|
||||
# to a timing simple CPU with caches to warm up, then to detailed CPU for
|
||||
|
@ -61,6 +65,7 @@ parser.add_option("-s", "--standard-switch", action="store_true",
|
|||
parser.add_option("-w", "--warmup", action="store", type="int",
|
||||
help="if -s, then this is the warmup period. else, this is ignored",
|
||||
default=5000000000)
|
||||
parser.add_option("--profile", help="CPU profile interval")
|
||||
|
||||
# Fastforwarding and simpoint related materials
|
||||
parser.add_option("-W", "--warmup-insts", action="store", type="int",
|
||||
|
|
|
@ -28,9 +28,13 @@
|
|||
|
||||
from os import getcwd
|
||||
from os.path import join as joinpath
|
||||
|
||||
import m5
|
||||
from m5.defines import buildEnv
|
||||
from m5.objects import *
|
||||
m5.AddToPath('../common')
|
||||
from m5.util import *
|
||||
|
||||
addToPath('../common')
|
||||
|
||||
def setCPUClass(options):
|
||||
|
||||
|
@ -82,10 +86,10 @@ def run(options, root, testsys, cpu_class):
|
|||
cptdir = getcwd()
|
||||
|
||||
if options.fast_forward and options.checkpoint_restore != None:
|
||||
m5.fatal("Error: Can't specify both --fast-forward and --checkpoint-restore")
|
||||
fatal("Can't specify both --fast-forward and --checkpoint-restore")
|
||||
|
||||
if options.standard_switch and not options.caches:
|
||||
m5.fatal("Error: Must specify --caches when using --standard-switch")
|
||||
fatal("Must specify --caches when using --standard-switch")
|
||||
|
||||
np = options.num_cpus
|
||||
max_checkpoints = options.max_checkpoints
|
||||
|
@ -95,6 +99,10 @@ def run(options, root, testsys, cpu_class):
|
|||
for i in xrange(np):
|
||||
testsys.cpu[i].progress_interval = options.prog_intvl
|
||||
|
||||
if options.maxinsts:
|
||||
for i in xrange(np):
|
||||
testsys.cpu[i].max_insts_any_thread = options.maxinsts
|
||||
|
||||
if cpu_class:
|
||||
switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
|
||||
for i in xrange(np)]
|
||||
|
@ -103,7 +111,7 @@ def run(options, root, testsys, cpu_class):
|
|||
if options.fast_forward:
|
||||
testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
|
||||
switch_cpus[i].system = testsys
|
||||
if not m5.build_env['FULL_SYSTEM']:
|
||||
if not buildEnv['FULL_SYSTEM']:
|
||||
switch_cpus[i].workload = testsys.cpu[i].workload
|
||||
switch_cpus[i].clock = testsys.cpu[0].clock
|
||||
# simulation period
|
||||
|
@ -122,7 +130,7 @@ def run(options, root, testsys, cpu_class):
|
|||
for i in xrange(np):
|
||||
switch_cpus[i].system = testsys
|
||||
switch_cpus_1[i].system = testsys
|
||||
if not m5.build_env['FULL_SYSTEM']:
|
||||
if not buildEnv['FULL_SYSTEM']:
|
||||
switch_cpus[i].workload = testsys.cpu[i].workload
|
||||
switch_cpus_1[i].workload = testsys.cpu[i].workload
|
||||
switch_cpus[i].clock = testsys.cpu[0].clock
|
||||
|
@ -137,7 +145,7 @@ def run(options, root, testsys, cpu_class):
|
|||
# Fast forward to a simpoint (warning: time consuming)
|
||||
elif options.simpoint:
|
||||
if testsys.cpu[i].workload[0].simpoint == 0:
|
||||
m5.fatal('simpoint not found')
|
||||
fatal('simpoint not found')
|
||||
testsys.cpu[i].max_insts_any_thread = \
|
||||
testsys.cpu[i].workload[0].simpoint
|
||||
# No distance specified, just switch
|
||||
|
@ -170,7 +178,7 @@ def run(options, root, testsys, cpu_class):
|
|||
if options.simpoint:
|
||||
for i in xrange(np):
|
||||
if testsys.cpu[i].workload[0].simpoint == 0:
|
||||
m5.fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
|
||||
fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
|
||||
checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
|
||||
testsys.cpu[i].max_insts_any_thread = checkpoint_inst
|
||||
# used for output below
|
||||
|
@ -190,14 +198,13 @@ def run(options, root, testsys, cpu_class):
|
|||
import re
|
||||
|
||||
if not isdir(cptdir):
|
||||
m5.fatal("checkpoint dir %s does not exist!", cptdir)
|
||||
fatal("checkpoint dir %s does not exist!", cptdir)
|
||||
|
||||
if options.at_instruction:
|
||||
checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
|
||||
(options.bench, options.checkpoint_restore))
|
||||
if not exists(checkpoint_dir):
|
||||
m5.fatal("Unable to find checkpoint directory %s",
|
||||
checkpoint_dir)
|
||||
fatal("Unable to find checkpoint directory %s", checkpoint_dir)
|
||||
|
||||
print "Restoring checkpoint ..."
|
||||
m5.restoreCheckpoint(root, checkpoint_dir)
|
||||
|
@ -205,7 +212,7 @@ def run(options, root, testsys, cpu_class):
|
|||
elif options.simpoint:
|
||||
# assume workload 0 has the simpoint
|
||||
if testsys.cpu[0].workload[0].simpoint == 0:
|
||||
m5.fatal('Unable to find simpoint')
|
||||
fatal('Unable to find simpoint')
|
||||
|
||||
options.checkpoint_restore += \
|
||||
int(testsys.cpu[0].workload[0].simpoint)
|
||||
|
@ -213,8 +220,8 @@ def run(options, root, testsys, cpu_class):
|
|||
checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
|
||||
(options.bench, options.checkpoint_restore))
|
||||
if not exists(checkpoint_dir):
|
||||
m5.fatal("Unable to find checkpoint directory %s.%s",
|
||||
options.bench, options.checkpoint_restore)
|
||||
fatal("Unable to find checkpoint directory %s.%s",
|
||||
options.bench, options.checkpoint_restore)
|
||||
|
||||
print "Restoring checkpoint ..."
|
||||
m5.restoreCheckpoint(root,checkpoint_dir)
|
||||
|
@ -233,7 +240,7 @@ def run(options, root, testsys, cpu_class):
|
|||
cpt_num = options.checkpoint_restore
|
||||
|
||||
if cpt_num > len(cpts):
|
||||
m5.fatal('Checkpoint %d not found', cpt_num)
|
||||
fatal('Checkpoint %d not found', cpt_num)
|
||||
|
||||
## Adjust max tick based on our starting tick
|
||||
maxtick = maxtick - int(cpts[cpt_num - 1])
|
||||
|
@ -367,3 +374,6 @@ def run(options, root, testsys, cpu_class):
|
|||
exit_cause = exit_event.getCause()
|
||||
print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause)
|
||||
|
||||
if options.checkpoint_at_end:
|
||||
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||
|
||||
|
|
|
@ -26,15 +26,20 @@
|
|||
#
|
||||
# Authors: Ali Saidi
|
||||
|
||||
import optparse, os, sys
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import m5
|
||||
|
||||
if not m5.build_env['FULL_SYSTEM']:
|
||||
m5.fatal("This script requires full-system mode (*_FS).")
|
||||
|
||||
from m5.defines import buildEnv
|
||||
from m5.objects import *
|
||||
m5.AddToPath('../common')
|
||||
from m5.util import addToPath, fatal
|
||||
|
||||
if not buildEnv['FULL_SYSTEM']:
|
||||
fatal("This script requires full-system mode (*_FS).")
|
||||
|
||||
addToPath('../common')
|
||||
|
||||
from FSConfig import *
|
||||
from SysPaths import *
|
||||
from Benchmarks import *
|
||||
|
@ -98,16 +103,16 @@ else:
|
|||
|
||||
np = options.num_cpus
|
||||
|
||||
if m5.build_env['TARGET_ISA'] == "alpha":
|
||||
if buildEnv['TARGET_ISA'] == "alpha":
|
||||
test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0])
|
||||
elif m5.build_env['TARGET_ISA'] == "mips":
|
||||
elif buildEnv['TARGET_ISA'] == "mips":
|
||||
test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0])
|
||||
elif m5.build_env['TARGET_ISA'] == "sparc":
|
||||
elif buildEnv['TARGET_ISA'] == "sparc":
|
||||
test_sys = makeSparcSystem(test_mem_mode, bm[0])
|
||||
elif m5.build_env['TARGET_ISA'] == "x86":
|
||||
elif buildEnv['TARGET_ISA'] == "x86":
|
||||
test_sys = makeLinuxX86System(test_mem_mode, np, bm[0])
|
||||
else:
|
||||
m5.fatal("incapable of building non-alpha or non-sparc full system!")
|
||||
fatal("incapable of building non-alpha or non-sparc full system!")
|
||||
|
||||
if options.kernel is not None:
|
||||
test_sys.kernel = binary(options.kernel)
|
||||
|
@ -123,7 +128,7 @@ if options.l2cache:
|
|||
|
||||
test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
|
||||
|
||||
if options.caches:
|
||||
if options.caches or options.l2cache:
|
||||
test_sys.bridge.filter_ranges_a=[AddrRange(0, Addr.max)]
|
||||
test_sys.bridge.filter_ranges_b=[AddrRange(0, size='8GB')]
|
||||
test_sys.iocache = IOCache(addr_range=AddrRange(0, size='8GB'))
|
||||
|
@ -142,17 +147,17 @@ for i in xrange(np):
|
|||
if options.fastmem:
|
||||
test_sys.cpu[i].physmem_port = test_sys.physmem.port
|
||||
|
||||
if m5.build_env['TARGET_ISA'] == 'mips':
|
||||
if buildEnv['TARGET_ISA'] == 'mips':
|
||||
setMipsOptions(TestCPUClass)
|
||||
|
||||
if len(bm) == 2:
|
||||
if m5.build_env['TARGET_ISA'] == 'alpha':
|
||||
if buildEnv['TARGET_ISA'] == 'alpha':
|
||||
drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
|
||||
elif m5.build_env['TARGET_ISA'] == 'mips':
|
||||
elif buildEnv['TARGET_ISA'] == 'mips':
|
||||
drive_sys = makeLinuxMipsSystem(drive_mem_mode, bm[1])
|
||||
elif m5.build_env['TARGET_ISA'] == 'sparc':
|
||||
elif buildEnv['TARGET_ISA'] == 'sparc':
|
||||
drive_sys = makeSparcSystem(drive_mem_mode, bm[1])
|
||||
elif m5.build.env['TARGET_ISA'] == 'x86':
|
||||
elif buildEnv['TARGET_ISA'] == 'x86':
|
||||
drive_sys = makeX86System(drive_mem_mode, np, bm[1])
|
||||
drive_sys.cpu = DriveCPUClass(cpu_id=0)
|
||||
drive_sys.cpu.connectMemPorts(drive_sys.membus)
|
||||
|
|
122
configs/example/memtest-ruby.py
Normal file
122
configs/example/memtest-ruby.py
Normal 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()
|
|
@ -26,10 +26,11 @@
|
|||
#
|
||||
# Authors: Ron Dreslinski
|
||||
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
import m5
|
||||
from m5.objects import *
|
||||
import os, optparse, sys
|
||||
m5.AddToPath('../common')
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
|
|
201
configs/example/ruby_fs.py
Normal file
201
configs/example/ruby_fs.py
Normal 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)
|
|
@ -30,17 +30,22 @@
|
|||
#
|
||||
# "m5 test.py"
|
||||
|
||||
import m5
|
||||
|
||||
if m5.build_env['FULL_SYSTEM']:
|
||||
m5.panic("This script requires syscall emulation mode (*_SE).")
|
||||
|
||||
from m5.objects import *
|
||||
import os, optparse, sys
|
||||
import os
|
||||
import optparse
|
||||
import sys
|
||||
from os.path import join as joinpath
|
||||
m5.AddToPath('../common')
|
||||
|
||||
import m5
|
||||
from m5.defines import buildEnv
|
||||
from m5.objects import *
|
||||
from m5.util import addToPath, panic
|
||||
|
||||
if buildEnv['FULL_SYSTEM']:
|
||||
panic("This script requires syscall emulation mode (*_SE).")
|
||||
|
||||
addToPath('../common')
|
||||
|
||||
import Simulation
|
||||
#from Caches import *
|
||||
from cpu2000 import *
|
||||
|
||||
# Get paths we might need. It's expected this file is in m5/configs/example.
|
||||
|
@ -72,7 +77,7 @@ if args:
|
|||
|
||||
if options.bench:
|
||||
try:
|
||||
if m5.build_env['TARGET_ISA'] != 'alpha':
|
||||
if buildEnv['TARGET_ISA'] != 'alpha':
|
||||
print >>sys.stderr, "Simpoints code only works for Alpha ISA at this time"
|
||||
sys.exit(1)
|
||||
exec("workload = %s('alpha', 'tru64', 'ref')" % options.bench)
|
||||
|
@ -133,7 +138,6 @@ rubymem = RubyMemory(
|
|||
range = AddrRange("512MB"),
|
||||
clock = "1GHz",
|
||||
num_cpus = np,
|
||||
libruby_file = "src/mem/ruby/amd64-linux/generated/MOESI_CMP_directory/bin/libruby.so",
|
||||
config_file = "ruby.config",
|
||||
stats_file = "m5out/ruby.stats"
|
||||
)
|
||||
|
|
|
@ -30,15 +30,21 @@
|
|||
#
|
||||
# "m5 test.py"
|
||||
|
||||
import m5
|
||||
|
||||
if m5.build_env['FULL_SYSTEM']:
|
||||
m5.fatal("This script requires syscall emulation mode (*_SE).")
|
||||
|
||||
from m5.objects import *
|
||||
import os, optparse, sys
|
||||
import os
|
||||
import optparse
|
||||
import sys
|
||||
from os.path import join as joinpath
|
||||
m5.AddToPath('../common')
|
||||
|
||||
import m5
|
||||
from m5.defines import buildEnv
|
||||
from m5.objects import *
|
||||
from m5.util import addToPath, fatal
|
||||
|
||||
if buildEnv['FULL_SYSTEM']:
|
||||
fatal("This script requires syscall emulation mode (*_SE).")
|
||||
|
||||
addToPath('../common')
|
||||
|
||||
import Simulation
|
||||
from Caches import *
|
||||
from cpu2000 import *
|
||||
|
@ -70,7 +76,7 @@ if args:
|
|||
|
||||
if options.bench:
|
||||
try:
|
||||
if m5.build_env['TARGET_ISA'] != 'alpha':
|
||||
if buildEnv['TARGET_ISA'] != 'alpha':
|
||||
print >>sys.stderr, "Simpoints code only works for Alpha ISA at this time"
|
||||
sys.exit(1)
|
||||
exec("workload = %s('alpha', 'tru64', 'ref')" % options.bench)
|
||||
|
@ -94,8 +100,9 @@ if options.errout != "":
|
|||
|
||||
# By default, set workload to path of user-specified binary
|
||||
workloads = options.cmd
|
||||
numThreads = 1
|
||||
|
||||
if options.detailed:
|
||||
if options.detailed or options.inorder:
|
||||
#check for SMT workload
|
||||
workloads = options.cmd.split(';')
|
||||
if len(workloads) > 1:
|
||||
|
@ -124,11 +131,12 @@ if options.detailed:
|
|||
smt_process.errout = errouts[smt_idx]
|
||||
process += [smt_process, ]
|
||||
smt_idx += 1
|
||||
numThreads = len(workloads)
|
||||
|
||||
(CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
|
||||
|
||||
CPUClass.clock = '2GHz'
|
||||
CPUClass.numThreads = len(workloads)
|
||||
CPUClass.numThreads = numThreads;
|
||||
|
||||
np = options.num_cpus
|
||||
|
||||
|
|
|
@ -30,10 +30,14 @@
|
|||
#
|
||||
# "m5 test.py"
|
||||
|
||||
import os
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
import m5
|
||||
from m5.objects import *
|
||||
import os, optparse, sys
|
||||
m5.AddToPath('../common')
|
||||
|
||||
m5.util.addToPath('../common')
|
||||
|
||||
# --------------------
|
||||
# Define Command Line Options
|
||||
|
@ -266,10 +270,11 @@ elif options.benchmark == 'WaterNSquared':
|
|||
elif options.benchmark == 'WaterSpatial':
|
||||
root.workload = Water_spatial()
|
||||
else:
|
||||
panic("The --benchmark environment variable was set to something" \
|
||||
+" improper.\nUse Cholesky, FFT, LUContig, LUNoncontig, Radix" \
|
||||
+", Barnes, FMM, OceanContig,\nOceanNoncontig, Raytrace," \
|
||||
+" WaterNSquared, or WaterSpatial\n")
|
||||
m5.util.panic("""
|
||||
The --benchmark environment variable was set to something improper.
|
||||
Use Cholesky, FFT, LUContig, LUNoncontig, Radix, Barnes, FMM, OceanContig,
|
||||
OceanNoncontig, Raytrace, WaterNSquared, or WaterSpatial
|
||||
""")
|
||||
|
||||
# --------------------
|
||||
# Assign the workload to the cpus
|
||||
|
|
|
@ -29,10 +29,14 @@
|
|||
# Splash2 Run Script
|
||||
#
|
||||
|
||||
import os
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
import m5
|
||||
from m5.objects import *
|
||||
import os, optparse, sys
|
||||
m5.AddToPath('../common')
|
||||
|
||||
m5.util.addToPath('../common')
|
||||
|
||||
# --------------------
|
||||
# Define Command Line Options
|
||||
|
|
100
src/SConscript
100
src/SConscript
|
@ -49,7 +49,7 @@ Import('*')
|
|||
# Children need to see the environment
|
||||
Export('env')
|
||||
|
||||
build_env = dict([(opt, env[opt]) for opt in export_vars])
|
||||
build_env = [(opt, env[opt]) for opt in export_vars]
|
||||
|
||||
########################################################################
|
||||
# Code for adding source files of various types
|
||||
|
@ -132,15 +132,15 @@ class PySource(SourceFile):
|
|||
modpath = '.'.join(modpath)
|
||||
|
||||
arcpath = path + [ self.basename ]
|
||||
debugname = self.snode.abspath
|
||||
if not exists(debugname):
|
||||
debugname = self.tnode.abspath
|
||||
abspath = self.snode.abspath
|
||||
if not exists(abspath):
|
||||
abspath = self.tnode.abspath
|
||||
|
||||
self.package = package
|
||||
self.modname = modname
|
||||
self.modpath = modpath
|
||||
self.arcname = joinpath(*arcpath)
|
||||
self.debugname = debugname
|
||||
self.abspath = abspath
|
||||
self.compiled = File(self.filename + 'c')
|
||||
self.assembly = File(self.filename + '.s')
|
||||
self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath)
|
||||
|
@ -228,9 +228,6 @@ env.Append(CPPPATH=Dir('.'))
|
|||
for extra_dir in extras_dir_list:
|
||||
env.Append(CPPPATH=Dir(extra_dir))
|
||||
|
||||
# Add a flag defining what THE_ISA should be for all compilation
|
||||
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
|
||||
|
||||
# Workaround for bug in SCons version > 0.97d20071212
|
||||
# Scons bug id: 2006 M5 Bug id: 308
|
||||
for root, dirs, files in os.walk(base_dir, topdown=True):
|
||||
|
@ -261,11 +258,38 @@ for extra_dir in extras_dir_list:
|
|||
for opt in export_vars:
|
||||
env.ConfigFile(opt)
|
||||
|
||||
def makeTheISA(source, target, env):
|
||||
f = file(str(target[0]), 'w')
|
||||
|
||||
isas = [ src.get_contents() for src in source ]
|
||||
target = env['TARGET_ISA']
|
||||
def define(isa):
|
||||
return isa.upper() + '_ISA'
|
||||
|
||||
def namespace(isa):
|
||||
return isa[0].upper() + isa[1:].lower() + 'ISA'
|
||||
|
||||
|
||||
print >>f, '#ifndef __CONFIG_THE_ISA_HH__'
|
||||
print >>f, '#define __CONFIG_THE_ISA_HH__'
|
||||
print >>f
|
||||
for i,isa in enumerate(isas):
|
||||
print >>f, '#define %s %d' % (define(isa), i + 1)
|
||||
print >>f
|
||||
print >>f, '#define THE_ISA %s' % (define(target))
|
||||
print >>f, '#define TheISA %s' % (namespace(target))
|
||||
print >>f
|
||||
print >>f, '#endif // __CONFIG_THE_ISA_HH__'
|
||||
|
||||
env.Command('config/the_isa.hh', map(Value, all_isa_list), makeTheISA)
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Prevent any SimObjects from being added after this point, they
|
||||
# should all have been added in the SConscripts above
|
||||
#
|
||||
SimObject.fixed = True
|
||||
|
||||
class DictImporter(object):
|
||||
'''This importer takes a dictionary of arbitrary module names that
|
||||
map to arbitrary filenames.'''
|
||||
|
@ -283,7 +307,7 @@ class DictImporter(object):
|
|||
self.installed = set()
|
||||
|
||||
def find_module(self, fullname, path):
|
||||
if fullname == 'defines':
|
||||
if fullname == 'm5.defines':
|
||||
return self
|
||||
|
||||
if fullname == 'm5.objects':
|
||||
|
@ -293,7 +317,7 @@ class DictImporter(object):
|
|||
return None
|
||||
|
||||
source = self.modules.get(fullname, None)
|
||||
if source is not None and exists(source.snode.abspath):
|
||||
if source is not None and fullname.startswith('m5.objects'):
|
||||
return self
|
||||
|
||||
return None
|
||||
|
@ -308,28 +332,31 @@ class DictImporter(object):
|
|||
mod.__path__ = fullname.split('.')
|
||||
return mod
|
||||
|
||||
if fullname == 'defines':
|
||||
mod.__dict__['buildEnv'] = build_env
|
||||
if fullname == 'm5.defines':
|
||||
mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
|
||||
return mod
|
||||
|
||||
source = self.modules[fullname]
|
||||
if source.modname == '__init__':
|
||||
mod.__path__ = source.modpath
|
||||
mod.__file__ = source.snode.abspath
|
||||
mod.__file__ = source.abspath
|
||||
|
||||
exec file(source.snode.abspath, 'r') in mod.__dict__
|
||||
exec file(source.abspath, 'r') in mod.__dict__
|
||||
|
||||
return mod
|
||||
|
||||
import m5.SimObject
|
||||
import m5.params
|
||||
|
||||
m5.SimObject.clear()
|
||||
m5.params.clear()
|
||||
|
||||
# install the python importer so we can grab stuff from the source
|
||||
# tree itself. We can't have SimObjects added after this point or
|
||||
# else we won't know about them for the rest of the stuff.
|
||||
SimObject.fixed = True
|
||||
importer = DictImporter(PySource.modules)
|
||||
sys.meta_path[0:0] = [ importer ]
|
||||
|
||||
import m5
|
||||
|
||||
# import all sim objects so we can populate the all_objects list
|
||||
# make sure that we're working with a list, then let's sort it
|
||||
for modname in SimObject.modnames:
|
||||
|
@ -346,6 +373,12 @@ all_enums = m5.params.allEnums
|
|||
all_params = {}
|
||||
for name,obj in sorted(sim_objects.iteritems()):
|
||||
for param in obj._params.local.values():
|
||||
# load the ptype attribute now because it depends on the
|
||||
# current version of SimObject.allClasses, but when scons
|
||||
# actually uses the value, all versions of
|
||||
# SimObject.allClasses will have been loaded
|
||||
param.ptype
|
||||
|
||||
if not hasattr(param, 'swig_decl'):
|
||||
continue
|
||||
pname = param.ptype_str
|
||||
|
@ -365,13 +398,27 @@ depends = [ PySource.modules[dep].tnode for dep in module_depends ]
|
|||
#
|
||||
|
||||
# Generate Python file containing a dict specifying the current
|
||||
# build_env flags.
|
||||
# buildEnv flags.
|
||||
def makeDefinesPyFile(target, source, env):
|
||||
f = file(str(target[0]), 'w')
|
||||
build_env, hg_info = [ x.get_contents() for x in source ]
|
||||
print >>f, "buildEnv = %s" % build_env
|
||||
print >>f, "hgRev = '%s'" % hg_info
|
||||
f.close()
|
||||
|
||||
code = m5.util.code_formatter()
|
||||
code("""
|
||||
import m5.internal
|
||||
import m5.util
|
||||
|
||||
buildEnv = m5.util.SmartDict($build_env)
|
||||
hgRev = '$hg_info'
|
||||
|
||||
compileDate = m5.internal.core.compileDate
|
||||
_globals = globals()
|
||||
for key,val in m5.internal.core.__dict__.iteritems():
|
||||
if key.startswith('flag_'):
|
||||
flag = key[5:]
|
||||
_globals[flag] = val
|
||||
del _globals
|
||||
""")
|
||||
code.write(str(target[0]))
|
||||
|
||||
defines_info = [ Value(build_env), Value(env['HG_INFO']) ]
|
||||
# Generate a file with all of the compile options in it
|
||||
|
@ -467,12 +514,7 @@ for name,simobj in sorted(sim_objects.iteritems()):
|
|||
# Generate any parameter header files needed
|
||||
params_i_files = []
|
||||
for name,param in all_params.iteritems():
|
||||
if isinstance(param, m5.params.VectorParamDesc):
|
||||
ext = 'vptype'
|
||||
else:
|
||||
ext = 'ptype'
|
||||
|
||||
i_file = File('params/%s_%s.i' % (name, ext))
|
||||
i_file = File('params/%s_%s.i' % (name, param.file_ext))
|
||||
params_i_files.append(i_file)
|
||||
env.Command(i_file, Value(name), createSwigParam)
|
||||
env.Depends(i_file, depends)
|
||||
|
@ -850,7 +892,7 @@ def objectifyPyFile(target, source, env):
|
|||
dst = file(str(target[0]), 'w')
|
||||
|
||||
pysource = PySource.tnodes[source[0]]
|
||||
compiled = compile(src, pysource.debugname, 'exec')
|
||||
compiled = compile(src, pysource.abspath, 'exec')
|
||||
marshalled = marshal.dumps(compiled)
|
||||
compressed = zlib.compress(marshalled)
|
||||
data = compressed
|
||||
|
|
|
@ -144,7 +144,7 @@ DtbFault::invoke(ThreadContext *tc)
|
|||
// read, like the EV5). The EV6 approach is cleaner and seems to
|
||||
// work with EV5 PAL code, but not the other way around.
|
||||
if (!tc->misspeculating() &&
|
||||
reqFlags.noneSet(Request::VPTE|Request::NO_FAULT)) {
|
||||
reqFlags.noneSet(Request::VPTE | Request::PREFETCH)) {
|
||||
// set VA register with faulting address
|
||||
tc->setMiscRegNoEffect(IPR_VA, vaddr);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace AlphaISA
|
|||
{
|
||||
|
||||
void
|
||||
ISA::serialize(std::ostream &os)
|
||||
ISA::serialize(EventManager *em, std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(fpcr);
|
||||
SERIALIZE_SCALAR(uniq);
|
||||
|
@ -46,7 +46,7 @@ ISA::serialize(std::ostream &os)
|
|||
}
|
||||
|
||||
void
|
||||
ISA::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(fpcr);
|
||||
UNSERIALIZE_SCALAR(uniq);
|
||||
|
|
|
@ -83,8 +83,9 @@ namespace AlphaISA
|
|||
intr_flag = 0;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
void serialize(EventManager *em, std::ostream &os);
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
|
||||
void reset(std::string core_name, ThreadID num_threads,
|
||||
unsigned num_vpes, BaseCPU *_cpu)
|
||||
|
|
|
@ -627,7 +627,7 @@ decode OPCODE default Unknown::unknown() {
|
|||
format MiscPrefetch {
|
||||
0xf800: wh64({{ EA = Rb & ~ULL(63); }},
|
||||
{{ xc->writeHint(EA, 64, memAccessFlags); }},
|
||||
mem_flags = NO_FAULT,
|
||||
mem_flags = PREFETCH,
|
||||
inst_flags = [IsMemRef, IsDataPrefetch,
|
||||
IsStore, MemWriteOp]);
|
||||
}
|
||||
|
|
|
@ -548,7 +548,7 @@ def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
|
|||
pf_flags = makeList(pf_flags)
|
||||
inst_flags = makeList(inst_flags)
|
||||
|
||||
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
|
||||
pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
|
||||
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
|
||||
'IsDataPrefetch', 'MemReadOp']
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ class AlphaLinux : public Linux
|
|||
static const unsigned TIOCISATTY_ = 0x2000745e;
|
||||
static const unsigned TIOCGETS_ = 0x402c7413;
|
||||
static const unsigned TIOCGETA_ = 0x40127417;
|
||||
static const unsigned TCSETAW_ = 0x80147419; // 2.6.15 kernel
|
||||
//@}
|
||||
|
||||
/// For table().
|
||||
|
@ -125,6 +126,21 @@ class AlphaLinux : public Linux
|
|||
TGT_RLIMIT_MEMLOCK = 9,
|
||||
TGT_RLIMIT_LOCKS = 10
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int64_t uptime; /* Seconds since boot */
|
||||
uint64_t loads[3]; /* 1, 5, and 15 minute load averages */
|
||||
uint64_t totalram; /* Total usable main memory size */
|
||||
uint64_t freeram; /* Available memory size */
|
||||
uint64_t sharedram; /* Amount of shared memory */
|
||||
uint64_t bufferram; /* Memory used by buffers */
|
||||
uint64_t totalswap; /* Total swap space size */
|
||||
uint64_t freeswap; /* swap space still available */
|
||||
uint16_t procs; /* Number of current processes */
|
||||
uint64_t totalhigh; /* Total high memory size */
|
||||
uint64_t freehigh; /* Available high memory size */
|
||||
uint64_t mem_unit; /* Memory unit size in bytes */
|
||||
} tgt_sysinfo;
|
||||
};
|
||||
|
||||
#endif // __ALPHA_ALPHA_LINUX_LINUX_HH__
|
||||
|
|
|
@ -48,7 +48,8 @@ static SyscallReturn
|
|||
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
|
||||
int index = 0;
|
||||
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
|
||||
|
||||
strcpy(name->sysname, "Linux");
|
||||
strcpy(name->nodename, "m5.eecs.umich.edu");
|
||||
|
@ -67,13 +68,15 @@ static SyscallReturn
|
|||
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
unsigned op = process->getSyscallArg(tc, 0);
|
||||
int index = 0;
|
||||
unsigned op = process->getSyscallArg(tc, index);
|
||||
Addr bufPtr = process->getSyscallArg(tc, index);
|
||||
// unsigned nbytes = process->getSyscallArg(tc, 2);
|
||||
|
||||
switch (op) {
|
||||
|
||||
case 45: { // GSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> fpcr(bufPtr);
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
*fpcr = 0;
|
||||
fpcr.copyOut(tc->getMemPort());
|
||||
|
@ -94,13 +97,15 @@ static SyscallReturn
|
|||
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
unsigned op = process->getSyscallArg(tc, 0);
|
||||
int index = 0;
|
||||
unsigned op = process->getSyscallArg(tc, index);
|
||||
Addr bufPtr = process->getSyscallArg(tc, index);
|
||||
// unsigned nbytes = process->getSyscallArg(tc, 2);
|
||||
|
||||
switch (op) {
|
||||
|
||||
case 14: { // SSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> fpcr(bufPtr);
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
fpcr.copyIn(tc->getMemPort());
|
||||
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
|
||||
|
@ -440,7 +445,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
|
|||
/* 315 */ SyscallDesc("munlock", unimplementedFunc),
|
||||
/* 316 */ SyscallDesc("mlockall", unimplementedFunc),
|
||||
/* 317 */ SyscallDesc("munlockall", unimplementedFunc),
|
||||
/* 318 */ SyscallDesc("sysinfo", unimplementedFunc),
|
||||
/* 318 */ SyscallDesc("sysinfo", sysinfoFunc<AlphaLinux>),
|
||||
/* 319 */ SyscallDesc("_sysctl", unimplementedFunc),
|
||||
/* 320 */ SyscallDesc("was sys_idle", unimplementedFunc),
|
||||
/* 321 */ SyscallDesc("oldumount", unimplementedFunc),
|
||||
|
|
|
@ -193,10 +193,10 @@ AlphaLiveProcess::startup()
|
|||
}
|
||||
|
||||
AlphaISA::IntReg
|
||||
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int i)
|
||||
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
|
||||
{
|
||||
assert(i < 6);
|
||||
return tc->readIntReg(FirstArgumentReg + i);
|
||||
return tc->readIntReg(FirstArgumentReg + i++);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -44,7 +44,7 @@ class AlphaLiveProcess : public LiveProcess
|
|||
void argsInit(int intSize, int pageSize);
|
||||
|
||||
public:
|
||||
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int i);
|
||||
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
|
||||
void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val);
|
||||
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
|
||||
};
|
||||
|
|
|
@ -45,7 +45,8 @@ static SyscallReturn
|
|||
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, 0));
|
||||
int index = 0;
|
||||
TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, index));
|
||||
|
||||
strcpy(name->sysname, "OSF1");
|
||||
strcpy(name->nodename, "m5.eecs.umich.edu");
|
||||
|
@ -62,35 +63,36 @@ static SyscallReturn
|
|||
getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
unsigned op = process->getSyscallArg(tc, 0);
|
||||
unsigned nbytes = process->getSyscallArg(tc, 2);
|
||||
int index = 0;
|
||||
unsigned op = process->getSyscallArg(tc, index);
|
||||
Addr bufPtr = process->getSyscallArg(tc, index);
|
||||
unsigned nbytes = process->getSyscallArg(tc, index);
|
||||
|
||||
switch (op) {
|
||||
|
||||
case AlphaTru64::GSI_MAX_CPU: {
|
||||
TypedBufferArg<uint32_t> max_cpu(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint32_t> max_cpu(bufPtr);
|
||||
*max_cpu = htog((uint32_t)process->numCpus());
|
||||
max_cpu.copyOut(tc->getMemPort());
|
||||
return 1;
|
||||
}
|
||||
|
||||
case AlphaTru64::GSI_CPUS_IN_BOX: {
|
||||
TypedBufferArg<uint32_t> cpus_in_box(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint32_t> cpus_in_box(bufPtr);
|
||||
*cpus_in_box = htog((uint32_t)process->numCpus());
|
||||
cpus_in_box.copyOut(tc->getMemPort());
|
||||
return 1;
|
||||
}
|
||||
|
||||
case AlphaTru64::GSI_PHYSMEM: {
|
||||
TypedBufferArg<uint64_t> physmem(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> physmem(bufPtr);
|
||||
*physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
|
||||
physmem.copyOut(tc->getMemPort());
|
||||
return 1;
|
||||
}
|
||||
|
||||
case AlphaTru64::GSI_CPU_INFO: {
|
||||
TypedBufferArg<AlphaTru64::cpu_info>
|
||||
infop(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<AlphaTru64::cpu_info> infop(bufPtr);
|
||||
|
||||
infop->current_cpu = htog(0);
|
||||
infop->cpus_in_box = htog(process->numCpus());
|
||||
|
@ -107,14 +109,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
}
|
||||
|
||||
case AlphaTru64::GSI_PROC_TYPE: {
|
||||
TypedBufferArg<uint64_t> proc_type(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> proc_type(bufPtr);
|
||||
*proc_type = htog((uint64_t)11);
|
||||
proc_type.copyOut(tc->getMemPort());
|
||||
return 1;
|
||||
}
|
||||
|
||||
case AlphaTru64::GSI_PLATFORM_NAME: {
|
||||
BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes);
|
||||
BufferArg bufArg(bufPtr, nbytes);
|
||||
strncpy((char *)bufArg.bufferPtr(),
|
||||
"COMPAQ Professional Workstation XP1000",
|
||||
nbytes);
|
||||
|
@ -123,7 +125,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
}
|
||||
|
||||
case AlphaTru64::GSI_CLK_TCK: {
|
||||
TypedBufferArg<uint64_t> clk_hz(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> clk_hz(bufPtr);
|
||||
*clk_hz = htog((uint64_t)1024);
|
||||
clk_hz.copyOut(tc->getMemPort());
|
||||
return 1;
|
||||
|
@ -142,12 +144,13 @@ static SyscallReturn
|
|||
setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
unsigned op = process->getSyscallArg(tc, 0);
|
||||
int index = 0;
|
||||
unsigned op = process->getSyscallArg(tc, index);
|
||||
|
||||
switch (op) {
|
||||
case AlphaTru64::SSI_IEEE_FP_CONTROL:
|
||||
warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
|
||||
process->getSyscallArg(tc, 1));
|
||||
process->getSyscallArg(tc, index));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -165,17 +168,19 @@ tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
{
|
||||
using namespace std;
|
||||
|
||||
int id = process->getSyscallArg(tc, 0); // table ID
|
||||
int index = process->getSyscallArg(tc, 1); // index into table
|
||||
int argIndex = 0;
|
||||
int id = process->getSyscallArg(tc, argIndex); // table ID
|
||||
int index = process->getSyscallArg(tc, argIndex); // index into table
|
||||
Addr bufPtr = process->getSyscallArg(tc, argIndex);
|
||||
// arg 2 is buffer pointer; type depends on table ID
|
||||
int nel = process->getSyscallArg(tc, 3); // number of elements
|
||||
int lel = process->getSyscallArg(tc, 4); // expected element size
|
||||
int nel = process->getSyscallArg(tc, argIndex); // number of elements
|
||||
int lel = process->getSyscallArg(tc, argIndex); // expected element size
|
||||
|
||||
switch (id) {
|
||||
case AlphaTru64::TBL_SYSINFO: {
|
||||
if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
|
||||
return -EINVAL;
|
||||
TypedBufferArg<Tru64::tbl_sysinfo> elp(process->getSyscallArg(tc, 2));
|
||||
TypedBufferArg<Tru64::tbl_sysinfo> elp(bufPtr);
|
||||
|
||||
const int clk_hz = one_million;
|
||||
elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
|
||||
|
|
|
@ -99,6 +99,7 @@ class AlphaTru64 : public Tru64
|
|||
static const unsigned TIOCISATTY_ = 0x2000745e;
|
||||
static const unsigned TIOCGETS_ = 0x402c7413;
|
||||
static const unsigned TIOCGETA_ = 0x40127417;
|
||||
static const unsigned TCSETAW_ = 0x80147419;
|
||||
//@}
|
||||
|
||||
//@{
|
||||
|
|
33
src/arch/arm/ArmInterrupts.py
Normal file
33
src/arch/arm/ArmInterrupts.py
Normal 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'
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2005 The Regents of The University of Michigan
|
||||
# Copyright (c) 2009 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -24,20 +24,12 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Authors: Nathan Binkert
|
||||
# Steve Reinhardt
|
||||
# Authors: Ali Saidi
|
||||
|
||||
import os
|
||||
from m5.params import *
|
||||
|
||||
# import the m5 compile options
|
||||
import defines
|
||||
from System import System
|
||||
|
||||
# make a SmartDict out of the build options for our local use
|
||||
import smartdict
|
||||
build_env = smartdict.SmartDict()
|
||||
build_env.update(defines.m5_build_env)
|
||||
|
||||
# make a SmartDict out of the OS environment too
|
||||
env = smartdict.SmartDict()
|
||||
env.update(os.environ)
|
||||
class ArmSystem(System):
|
||||
type = 'ArmSystem'
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2007-2008 The Florida State University
|
||||
# Copyright (c) 2009 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -27,6 +28,7 @@
|
|||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Authors: Stephen Hines
|
||||
# Ali Saidi
|
||||
|
||||
Import('*')
|
||||
|
||||
|
@ -43,15 +45,20 @@ if env['TARGET_ISA'] == 'arm':
|
|||
Source('pagetable.cc')
|
||||
Source('tlb.cc')
|
||||
Source('vtophys.cc')
|
||||
Source('utility.cc')
|
||||
|
||||
SimObject('ArmNativeTrace.py')
|
||||
SimObject('ArmTLB.py')
|
||||
|
||||
TraceFlag('Arm')
|
||||
|
||||
TraceFlag('Faults', "Trace Exceptions, interrupts, svc/swi")
|
||||
if env['FULL_SYSTEM']:
|
||||
#Insert Full-System Files Here
|
||||
pass
|
||||
Source('interrupts.cc')
|
||||
Source('stacktrace.cc')
|
||||
Source('system.cc')
|
||||
|
||||
SimObject('ArmInterrupts.py')
|
||||
SimObject('ArmSystem.py')
|
||||
else:
|
||||
Source('process.cc')
|
||||
Source('linux/linux.cc')
|
||||
|
|
|
@ -26,488 +26,114 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
* Stephen Hines
|
||||
* Authors: Ali Saidi
|
||||
* Gabe Black
|
||||
*/
|
||||
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "base/trace.hh"
|
||||
#if !FULL_SYSTEM
|
||||
#include "sim/process.hh"
|
||||
#include "mem/page_table.hh"
|
||||
#endif
|
||||
|
||||
namespace ArmISA
|
||||
{
|
||||
|
||||
FaultName MachineCheckFault::_name = "Machine Check";
|
||||
FaultVect MachineCheckFault::_vect = 0x0401;
|
||||
FaultStat MachineCheckFault::_count;
|
||||
template<> ArmFaultBase::FaultVals ArmFault<Reset>::vals =
|
||||
{"reset", 0x00, MODE_SVC, 0, 0, true, true};
|
||||
|
||||
FaultName AlignmentFault::_name = "Alignment";
|
||||
FaultVect AlignmentFault::_vect = 0x0301;
|
||||
FaultStat AlignmentFault::_count;
|
||||
template<> ArmFaultBase::FaultVals ArmFault<UndefinedInstruction>::vals =
|
||||
{"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ;
|
||||
|
||||
FaultName ResetFault::_name = "Reset Fault";
|
||||
#if FULL_SYSTEM
|
||||
FaultVect ResetFault::_vect = 0xBFC00000;
|
||||
#else
|
||||
FaultVect ResetFault::_vect = 0x001;
|
||||
#endif
|
||||
FaultStat ResetFault::_count;
|
||||
template<> ArmFaultBase::FaultVals ArmFault<SupervisorCall>::vals =
|
||||
{"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false};
|
||||
|
||||
FaultName AddressErrorFault::_name = "Address Error";
|
||||
FaultVect AddressErrorFault::_vect = 0x0180;
|
||||
FaultStat AddressErrorFault::_count;
|
||||
template<> ArmFaultBase::FaultVals ArmFault<PrefetchAbort>::vals =
|
||||
{"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false};
|
||||
|
||||
FaultName StoreAddressErrorFault::_name = "Store Address Error";
|
||||
FaultVect StoreAddressErrorFault::_vect = 0x0180;
|
||||
FaultStat StoreAddressErrorFault::_count;
|
||||
template<> ArmFaultBase::FaultVals ArmFault<DataAbort>::vals =
|
||||
{"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false};
|
||||
|
||||
template<> ArmFaultBase::FaultVals ArmFault<Interrupt>::vals =
|
||||
{"IRQ", 0x18, MODE_IRQ, 4, 4, true, false};
|
||||
|
||||
FaultName SystemCallFault::_name = "Syscall";
|
||||
FaultVect SystemCallFault::_vect = 0x0180;
|
||||
FaultStat SystemCallFault::_count;
|
||||
template<> ArmFaultBase::FaultVals ArmFault<FastInterrupt>::vals =
|
||||
{"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
|
||||
|
||||
FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault";
|
||||
FaultVect CoprocessorUnusableFault::_vect = 0x180;
|
||||
FaultStat CoprocessorUnusableFault::_count;
|
||||
|
||||
FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault";
|
||||
FaultVect ReservedInstructionFault::_vect = 0x0180;
|
||||
FaultStat ReservedInstructionFault::_count;
|
||||
|
||||
FaultName ThreadFault::_name = "Thread Fault";
|
||||
FaultVect ThreadFault::_vect = 0x00F1;
|
||||
FaultStat ThreadFault::_count;
|
||||
|
||||
|
||||
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
|
||||
FaultVect ArithmeticFault::_vect = 0x180;
|
||||
FaultStat ArithmeticFault::_count;
|
||||
|
||||
FaultName UnimplementedOpcodeFault::_name = "opdec";
|
||||
FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
|
||||
FaultStat UnimplementedOpcodeFault::_count;
|
||||
|
||||
FaultName InterruptFault::_name = "interrupt";
|
||||
FaultVect InterruptFault::_vect = 0x0180;
|
||||
FaultStat InterruptFault::_count;
|
||||
|
||||
FaultName TrapFault::_name = "Trap";
|
||||
FaultVect TrapFault::_vect = 0x0180;
|
||||
FaultStat TrapFault::_count;
|
||||
|
||||
FaultName BreakpointFault::_name = "Breakpoint";
|
||||
FaultVect BreakpointFault::_vect = 0x0180;
|
||||
FaultStat BreakpointFault::_count;
|
||||
|
||||
|
||||
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
|
||||
FaultVect ItbInvalidFault::_vect = 0x0180;
|
||||
FaultStat ItbInvalidFault::_count;
|
||||
|
||||
FaultName ItbPageFault::_name = "itbmiss";
|
||||
FaultVect ItbPageFault::_vect = 0x0181;
|
||||
FaultStat ItbPageFault::_count;
|
||||
|
||||
FaultName ItbMissFault::_name = "itbmiss";
|
||||
FaultVect ItbMissFault::_vect = 0x0181;
|
||||
FaultStat ItbMissFault::_count;
|
||||
|
||||
FaultName ItbAcvFault::_name = "iaccvio";
|
||||
FaultVect ItbAcvFault::_vect = 0x0081;
|
||||
FaultStat ItbAcvFault::_count;
|
||||
|
||||
FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)";
|
||||
FaultVect ItbRefillFault::_vect = 0x0180;
|
||||
FaultStat ItbRefillFault::_count;
|
||||
|
||||
FaultName NDtbMissFault::_name = "dtb_miss_single";
|
||||
FaultVect NDtbMissFault::_vect = 0x0201;
|
||||
FaultStat NDtbMissFault::_count;
|
||||
|
||||
FaultName PDtbMissFault::_name = "dtb_miss_double";
|
||||
FaultVect PDtbMissFault::_vect = 0x0281;
|
||||
FaultStat PDtbMissFault::_count;
|
||||
|
||||
FaultName DtbPageFault::_name = "dfault";
|
||||
FaultVect DtbPageFault::_vect = 0x0381;
|
||||
FaultStat DtbPageFault::_count;
|
||||
|
||||
FaultName DtbAcvFault::_name = "dfault";
|
||||
FaultVect DtbAcvFault::_vect = 0x0381;
|
||||
FaultStat DtbAcvFault::_count;
|
||||
|
||||
FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)";
|
||||
FaultVect DtbInvalidFault::_vect = 0x0180;
|
||||
FaultStat DtbInvalidFault::_count;
|
||||
|
||||
FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)";
|
||||
FaultVect DtbRefillFault::_vect = 0x0180;
|
||||
FaultStat DtbRefillFault::_count;
|
||||
|
||||
FaultName TLBModifiedFault::_name = "TLB Modified Exception";
|
||||
FaultVect TLBModifiedFault::_vect = 0x0180;
|
||||
FaultStat TLBModifiedFault::_count;
|
||||
|
||||
FaultName FloatEnableFault::_name = "float_enable_fault";
|
||||
FaultVect FloatEnableFault::_vect = 0x0581;
|
||||
FaultStat FloatEnableFault::_count;
|
||||
|
||||
FaultName IntegerOverflowFault::_name = "Integer Overflow Fault";
|
||||
FaultVect IntegerOverflowFault::_vect = 0x0501;
|
||||
FaultStat IntegerOverflowFault::_count;
|
||||
|
||||
FaultName DspStateDisabledFault::_name = "DSP Disabled Fault";
|
||||
FaultVect DspStateDisabledFault::_vect = 0x001a;
|
||||
FaultStat DspStateDisabledFault::_count;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void ArmFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
|
||||
Addr
|
||||
ArmFaultBase::getVector(ThreadContext *tc)
|
||||
{
|
||||
tc->setPC(HandlerBase);
|
||||
tc->setNextPC(HandlerBase+sizeof(MachInst));
|
||||
tc->setNextNPC(HandlerBase+2*sizeof(MachInst));
|
||||
// ARM ARM B1-3
|
||||
|
||||
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
|
||||
|
||||
// panic if SCTLR.VE because I have no idea what to do with vectored
|
||||
// interrupts
|
||||
assert(!sctlr.ve);
|
||||
|
||||
if (!sctlr.v)
|
||||
return offset();
|
||||
return offset() + HighVecs;
|
||||
|
||||
}
|
||||
|
||||
void ArmFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode)
|
||||
#if FULL_SYSTEM
|
||||
|
||||
void
|
||||
ArmFaultBase::invoke(ThreadContext *tc)
|
||||
{
|
||||
// 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);
|
||||
// ARM ARM B1.6.3
|
||||
FaultBase::invoke(tc);
|
||||
countStat()++;
|
||||
|
||||
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
|
||||
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||
CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
|
||||
tc->readIntReg(INTREG_CONDCODES);
|
||||
|
||||
|
||||
cpsr.mode = nextMode();
|
||||
cpsr.it1 = cpsr.it2 = 0;
|
||||
cpsr.j = 0;
|
||||
|
||||
if (sctlr.te)
|
||||
cpsr.t = 1;
|
||||
cpsr.a = cpsr.a | abortDisable();
|
||||
cpsr.f = cpsr.f | fiqDisable();
|
||||
cpsr.i = 1;
|
||||
tc->setMiscReg(MISCREG_CPSR, cpsr);
|
||||
tc->setIntReg(INTREG_LR, tc->readPC() +
|
||||
(saved_cpsr.t ? thumbPcOffset() : armPcOffset()));
|
||||
|
||||
switch (nextMode()) {
|
||||
case MODE_FIQ:
|
||||
tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
|
||||
break;
|
||||
case MODE_IRQ:
|
||||
tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
|
||||
break;
|
||||
case MODE_SVC:
|
||||
tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
|
||||
break;
|
||||
case MODE_UNDEFINED:
|
||||
tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
|
||||
break;
|
||||
case MODE_ABORT:
|
||||
tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
|
||||
break;
|
||||
default:
|
||||
panic("unknown Mode\n");
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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 ArithmeticFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0xC);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
MiscReg stat = tc->readMiscReg(ArmISA::Status);
|
||||
// Here, the handler is dependent on BEV, which is not modified by setExceptionState()
|
||||
if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase);
|
||||
}else{
|
||||
HandlerBase = 0xBFC00200;
|
||||
}
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
||||
}
|
||||
|
||||
void StoreAddressErrorFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x5);
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
|
||||
}
|
||||
|
||||
void TrapFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
// warn("%s encountered.\n", name());
|
||||
setExceptionState(tc,0xD);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
}
|
||||
|
||||
void BreakpointFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
setExceptionState(tc,0x9);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
|
||||
}
|
||||
|
||||
void DtbInvalidFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
// warn("%s encountered.\n", name());
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
|
||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
||||
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
|
||||
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
|
||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
||||
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
|
||||
setExceptionState(tc,0x3);
|
||||
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
}
|
||||
|
||||
void AddressErrorFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x4);
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
}
|
||||
|
||||
void ItbInvalidFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x2);
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
|
||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
||||
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
|
||||
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
|
||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
||||
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
|
||||
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
DPRINTF(Arm,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
}
|
||||
|
||||
void ItbRefillFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered (%x).\n", name(),BadVAddr);
|
||||
Addr HandlerBase;
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
|
||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
||||
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
|
||||
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
|
||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
||||
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
|
||||
|
||||
MiscReg stat = tc->readMiscReg(ArmISA::Status);
|
||||
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
||||
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
}else{
|
||||
HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000
|
||||
}
|
||||
|
||||
setExceptionState(tc,0x2);
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
}
|
||||
|
||||
void DtbRefillFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
// Set new PC
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
Addr HandlerBase;
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
|
||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
||||
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
|
||||
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
|
||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
||||
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
|
||||
|
||||
MiscReg stat = tc->readMiscReg(ArmISA::Status);
|
||||
// Since handler depends on EXL bit, must check EXL bit before setting it!!
|
||||
if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
}else{
|
||||
HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000
|
||||
}
|
||||
|
||||
|
||||
setExceptionState(tc,0x3);
|
||||
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
}
|
||||
|
||||
void TLBModifiedFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr);
|
||||
MiscReg eh = tc->readMiscReg(ArmISA::EntryHi);
|
||||
replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
|
||||
replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
|
||||
replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
|
||||
tc->setMiscRegNoEffect(ArmISA::EntryHi,eh);
|
||||
MiscReg ctxt = tc->readMiscReg(ArmISA::Context);
|
||||
replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
|
||||
tc->setMiscRegNoEffect(ArmISA::Context,ctxt);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setExceptionState(tc,0x1);
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
|
||||
}
|
||||
|
||||
void SystemCallFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x8);
|
||||
|
||||
// Set new PC
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
// warn("Exception Handler At: %x \n",HandlerBase);
|
||||
// warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC));
|
||||
|
||||
}
|
||||
|
||||
void InterruptFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x0A);
|
||||
Addr HandlerBase;
|
||||
|
||||
|
||||
uint8_t IV = bits(tc->readMiscRegNoEffect(ArmISA::Cause),Cause_IV);
|
||||
if (IV)// Offset 200 for release 2
|
||||
HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(ArmISA::EBase);
|
||||
else//Ofset at 180 for release 1
|
||||
HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase);
|
||||
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
void ResetFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
/* All reset activity must be invoked from here */
|
||||
tc->setPC(vect());
|
||||
tc->setNextPC(vect()+sizeof(MachInst));
|
||||
tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst));
|
||||
DPRINTF(Arm,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC());
|
||||
#endif
|
||||
// return via SUBS pc, lr, xxx; rfe, movs, ldm
|
||||
|
||||
// Set Coprocessor 1 (Floating Point) To Usable
|
||||
//tc->setMiscReg(ArmISA::Status, ArmISA::Status | 0x20000000);
|
||||
}
|
||||
|
||||
void ReservedInstructionFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0x0A);
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
#else
|
||||
panic("%s encountered.\n", name());
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
panic("%s encountered.\n", name());
|
||||
}
|
||||
|
||||
void DspStateDisabledFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
panic("%s encountered.\n", name());
|
||||
}
|
||||
|
||||
void CoprocessorUnusableFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
DPRINTF(Arm,"%s encountered.\n", name());
|
||||
setExceptionState(tc,0xb);
|
||||
/* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */
|
||||
MiscReg cause = tc->readMiscReg(ArmISA::Cause);
|
||||
replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID);
|
||||
tc->setMiscRegNoEffect(ArmISA::Cause,cause);
|
||||
|
||||
Addr HandlerBase;
|
||||
HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector
|
||||
setHandlerPC(HandlerBase,tc);
|
||||
|
||||
// warn("Status: %x, Cause: %x\n",tc->readMiscReg(ArmISA::Status),tc->readMiscReg(ArmISA::Cause));
|
||||
#else
|
||||
warn("%s (CP%d) encountered.\n", name(), coProcID);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
|
|
|
@ -26,548 +26,79 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
* Stephen Hines
|
||||
* Authors: Ali Saidi
|
||||
* Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef __ARM_FAULTS_HH__
|
||||
#define __ARM_FAULTS_HH__
|
||||
|
||||
#include "arch/arm/types.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "sim/faults.hh"
|
||||
|
||||
// The design of the "name" and "vect" functions is in sim/faults.hh
|
||||
|
||||
namespace ArmISA
|
||||
{
|
||||
typedef const Addr FaultVect;
|
||||
typedef const Addr FaultOffset;
|
||||
|
||||
class ArmFault : public FaultBase
|
||||
class ArmFaultBase : public FaultBase
|
||||
{
|
||||
protected:
|
||||
virtual bool skipFaultingInstruction() {return false;}
|
||||
virtual bool setRestartAddress() {return true;}
|
||||
Addr getVector(ThreadContext *tc);
|
||||
|
||||
public:
|
||||
Addr BadVAddr;
|
||||
Addr EntryHi_Asid;
|
||||
Addr EntryHi_VPN2;
|
||||
Addr EntryHi_VPN2X;
|
||||
Addr Context_BadVPN2;
|
||||
struct FaultVals
|
||||
{
|
||||
const FaultName name;
|
||||
const FaultOffset offset;
|
||||
const OperatingMode nextMode;
|
||||
const uint8_t armPcOffset;
|
||||
const uint8_t thumbPcOffset;
|
||||
const bool abortDisable;
|
||||
const bool fiqDisable;
|
||||
FaultStat count;
|
||||
};
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc) {};
|
||||
void setExceptionState(ThreadContext *,uint8_t);
|
||||
void setHandlerPC(Addr,ThreadContext *);
|
||||
void invoke(ThreadContext *tc);
|
||||
#endif
|
||||
virtual FaultVect vect() = 0;
|
||||
virtual FaultStat & countStat() = 0;
|
||||
virtual FaultStat& countStat() = 0;
|
||||
virtual FaultOffset offset() = 0;
|
||||
virtual OperatingMode nextMode() = 0;
|
||||
virtual uint8_t armPcOffset() = 0;
|
||||
virtual uint8_t thumbPcOffset() = 0;
|
||||
virtual bool abortDisable() = 0;
|
||||
virtual bool fiqDisable() = 0;
|
||||
};
|
||||
|
||||
class MachineCheckFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
bool isMachineCheckFault() {return true;}
|
||||
};
|
||||
|
||||
class NonMaskableInterrupt : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
bool isNonMaskableInterrupt() {return true;}
|
||||
};
|
||||
|
||||
class AlignmentFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
bool isAlignmentFault() {return true;}
|
||||
};
|
||||
|
||||
class AddressErrorFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
class StoreAddressErrorFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
class UnimplementedOpcodeFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
|
||||
class TLBRefillIFetchFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
Addr vaddr;
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
class TLBInvalidIFetchFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
Addr vaddr;
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class NDtbMissFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class PDtbMissFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class DtbPageFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class DtbAcvFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class CacheErrorFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
Addr vaddr;
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static inline Fault genMachineCheckFault()
|
||||
{
|
||||
return new MachineCheckFault;
|
||||
}
|
||||
|
||||
static inline Fault genAlignmentFault()
|
||||
{
|
||||
return new AlignmentFault;
|
||||
}
|
||||
|
||||
class ResetFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
|
||||
};
|
||||
class SystemCallFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class SoftResetFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
class DebugSingleStep : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
class DebugInterrupt : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class CoprocessorUnusableFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
int coProcID;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
CoprocessorUnusableFault(int _procid){ coProcID = _procid;}
|
||||
};
|
||||
|
||||
class ReservedInstructionFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class ThreadFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
|
||||
class ArithmeticFault : public ArmFault
|
||||
template<typename T>
|
||||
class ArmFault : public ArmFaultBase
|
||||
{
|
||||
protected:
|
||||
bool skipFaultingInstruction() {return true;}
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
static FaultVals vals;
|
||||
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
FaultName name() const { return vals.name; }
|
||||
FaultStat & countStat() {return vals.count;}
|
||||
FaultOffset offset() { return vals.offset; }
|
||||
OperatingMode nextMode() { return vals.nextMode; }
|
||||
uint8_t armPcOffset() { return vals.armPcOffset; }
|
||||
uint8_t thumbPcOffset() { return vals.thumbPcOffset; }
|
||||
bool abortDisable() { return vals.abortDisable; }
|
||||
bool fiqDisable() { return vals.fiqDisable; }
|
||||
};
|
||||
|
||||
class InterruptFault : public ArmFault
|
||||
{
|
||||
protected:
|
||||
bool setRestartAddress() {return false;}
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
class Reset : public ArmFault<Reset> {};
|
||||
class UndefinedInstruction : public ArmFault<UndefinedInstruction> {};
|
||||
class SupervisorCall : public ArmFault<SupervisorCall> {};
|
||||
class PrefetchAbort : public ArmFault<PrefetchAbort> {};
|
||||
class DataAbort : public ArmFault<DataAbort> {};
|
||||
class Interrupt : public ArmFault<Interrupt> {};
|
||||
class FastInterrupt : public ArmFault<FastInterrupt> {};
|
||||
|
||||
//void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class TrapFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class BreakpointFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class ItbRefillFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
class DtbRefillFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class ItbPageFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
};
|
||||
|
||||
class ItbInvalidFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
class TLBModifiedFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class DtbInvalidFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
#if FULL_SYSTEM
|
||||
void invoke(ThreadContext * tc);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class FloatEnableFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class ItbMissFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class ItbAcvFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class IntegerOverflowFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
};
|
||||
|
||||
class DspStateDisabledFault : public ArmFault
|
||||
{
|
||||
private:
|
||||
static FaultName _name;
|
||||
static FaultVect _vect;
|
||||
static FaultStat _count;
|
||||
public:
|
||||
FaultName name() const {return _name;}
|
||||
FaultVect vect() {return _vect;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
} // ArmISA namespace
|
||||
|
||||
|
|
|
@ -84,33 +84,20 @@ class MicroMemOp : public MicroIntOp
|
|||
*/
|
||||
class ArmMacroMemoryOp : public PredMacroOp
|
||||
{
|
||||
protected:
|
||||
protected:
|
||||
/// Memory request flags. See mem_req_base.hh.
|
||||
unsigned memAccessFlags;
|
||||
|
||||
uint32_t reglist;
|
||||
uint32_t ones;
|
||||
uint32_t puswl,
|
||||
prepost,
|
||||
up,
|
||||
psruser,
|
||||
writeback,
|
||||
loadop;
|
||||
|
||||
ArmMacroMemoryOp(const char *mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass)
|
||||
: PredMacroOp(mnem, _machInst, __opClass),
|
||||
memAccessFlags(0),
|
||||
reglist(machInst.regList), ones(0),
|
||||
puswl(machInst.puswl),
|
||||
prepost(machInst.puswl.prepost),
|
||||
up(machInst.puswl.up),
|
||||
psruser(machInst.puswl.psruser),
|
||||
writeback(machInst.puswl.writeback),
|
||||
loadop(machInst.puswl.loadOp)
|
||||
: PredMacroOp(mnem, _machInst, __opClass), memAccessFlags(0),
|
||||
reglist(machInst.regList), ones(0)
|
||||
{
|
||||
ones = number_of_ones(reglist);
|
||||
numMicroops = ones + writeback + 1;
|
||||
numMicroops = ones + machInst.puswl.writeback + 1;
|
||||
// Remember that writeback adds a uop
|
||||
microOps = new StaticInstPtr[numMicroops];
|
||||
}
|
||||
|
@ -121,7 +108,7 @@ class ArmMacroMemoryOp : public PredMacroOp
|
|||
*/
|
||||
class ArmMacroFPAOp : public PredMacroOp
|
||||
{
|
||||
protected:
|
||||
protected:
|
||||
uint32_t puswl,
|
||||
prepost,
|
||||
up,
|
||||
|
@ -150,7 +137,7 @@ class ArmMacroFPAOp : public PredMacroOp
|
|||
*/
|
||||
class ArmMacroFMOp : public PredMacroOp
|
||||
{
|
||||
protected:
|
||||
protected:
|
||||
uint32_t punwl,
|
||||
prepost,
|
||||
up,
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
* Authors: Stephen Hines
|
||||
*/
|
||||
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/insts/static_inst.hh"
|
||||
#include "base/condcodes.hh"
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
|
||||
namespace ArmISA
|
||||
|
@ -62,7 +64,7 @@ ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
|
|||
else
|
||||
return (base << (32 - shamt)) | (base >> shamt);
|
||||
default:
|
||||
fprintf(stderr, "Unhandled shift type\n");
|
||||
ccprintf(std::cerr, "Unhandled shift type\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
|
|||
else
|
||||
return (base << (32 - shamt)) | (base >> shamt);
|
||||
default:
|
||||
fprintf(stderr, "Unhandled shift type\n");
|
||||
ccprintf(std::cerr, "Unhandled shift type\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
@ -141,7 +143,7 @@ ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
|
|||
else
|
||||
return (base >> (shamt - 1)) & 1;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled shift type\n");
|
||||
ccprintf(std::cerr, "Unhandled shift type\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
@ -182,7 +184,7 @@ ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
|
|||
shamt = 32;
|
||||
return (base >> (shamt - 1)) & 1;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled shift type\n");
|
||||
ccprintf(std::cerr, "Unhandled shift type\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,56 @@ class ArmStaticInst : public StaticInst
|
|||
void printDataInst(std::ostream &os, bool withImm) const;
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
|
||||
static uint32_t
|
||||
cpsrWriteByInstr(CPSR cpsr, uint32_t val,
|
||||
uint8_t byteMask, bool affectState)
|
||||
{
|
||||
bool privileged = (cpsr.mode != MODE_USER);
|
||||
|
||||
uint32_t bitMask = 0;
|
||||
|
||||
if (bits(byteMask, 3)) {
|
||||
unsigned lowIdx = affectState ? 24 : 27;
|
||||
bitMask = bitMask | mask(31, lowIdx);
|
||||
}
|
||||
if (bits(byteMask, 2)) {
|
||||
bitMask = bitMask | mask(19, 16);
|
||||
}
|
||||
if (bits(byteMask, 1)) {
|
||||
unsigned highIdx = affectState ? 15 : 9;
|
||||
unsigned lowIdx = privileged ? 8 : 9;
|
||||
bitMask = bitMask | mask(highIdx, lowIdx);
|
||||
}
|
||||
if (bits(byteMask, 0)) {
|
||||
if (privileged) {
|
||||
bitMask = bitMask | mask(7, 6);
|
||||
bitMask = bitMask | mask(5);
|
||||
}
|
||||
if (affectState)
|
||||
bitMask = bitMask | (1 << 5);
|
||||
}
|
||||
|
||||
return ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
spsrWriteByInstr(uint32_t spsr, uint32_t val,
|
||||
uint8_t byteMask, bool affectState)
|
||||
{
|
||||
uint32_t bitMask = 0;
|
||||
|
||||
if (bits(byteMask, 3))
|
||||
bitMask = bitMask | mask(31, 24);
|
||||
if (bits(byteMask, 2))
|
||||
bitMask = bitMask | mask(19, 16);
|
||||
if (bits(byteMask, 1))
|
||||
bitMask = bitMask | mask(15, 8);
|
||||
if (bits(byteMask, 0))
|
||||
bitMask = bitMask | mask(7, 0);
|
||||
|
||||
return ((spsr & ~bitMask) | (val & bitMask));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,15 +24,14 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/*
|
||||
* AST.C
|
||||
*
|
||||
* Description: See AST.hh
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#include "arch/arm/interrupts.hh"
|
||||
|
||||
#include "mem/slicc/ast/AST.hh"
|
||||
ArmISA::Interrupts *
|
||||
ArmInterruptsParams::create()
|
||||
{
|
||||
return new ArmISA::Interrupts(this);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* Copyright (c) 2009 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,59 +25,97 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/*
|
||||
* LiteralExprAST.hh
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* $Id: LiteralExprAST.hh,v 3.1 2001/12/12 01:00:20 milo Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_ARM_INTERRUPT_HH__
|
||||
#define __ARCH_ARM_INTERRUPT_HH__
|
||||
|
||||
#ifndef LITERALEXPRAST_H
|
||||
#define LITERALEXPRAST_H
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/isa_traits.hh"
|
||||
#include "arch/arm/registers.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "params/ArmInterrupts.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
#include "mem/slicc/slicc_global.hh"
|
||||
#include "mem/slicc/ast/ExprAST.hh"
|
||||
|
||||
|
||||
class LiteralExprAST : public ExprAST {
|
||||
public:
|
||||
// Constructors
|
||||
LiteralExprAST(string* lit_ptr, string type) : ExprAST() { m_lit_ptr = lit_ptr; m_type = type; }
|
||||
|
||||
// Destructor
|
||||
~LiteralExprAST() { delete m_lit_ptr; }
|
||||
|
||||
// Public Methods
|
||||
Type* generate(string& code) const;
|
||||
void print(ostream& out) const { out << "[Literal: " << *m_lit_ptr << "]"; }
|
||||
private:
|
||||
// Private Methods
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
LiteralExprAST(const LiteralExprAST& obj);
|
||||
LiteralExprAST& operator=(const LiteralExprAST& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
string* m_lit_ptr;
|
||||
string m_type;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const LiteralExprAST& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const LiteralExprAST& obj)
|
||||
namespace ArmISA
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //LITERALEXPRAST_H
|
||||
class Interrupts : public SimObject
|
||||
{
|
||||
private:
|
||||
BaseCPU * cpu;
|
||||
|
||||
uint64_t intStatus;
|
||||
|
||||
public:
|
||||
|
||||
void
|
||||
setCPU(BaseCPU * _cpu)
|
||||
{
|
||||
cpu = _cpu;
|
||||
}
|
||||
|
||||
typedef ArmInterruptsParams Params;
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
Interrupts(Params * p) : SimObject(p), cpu(NULL)
|
||||
{
|
||||
clearAll();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
post(int int_num, int index)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
clear(int int_num, int index)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
clearAll()
|
||||
{
|
||||
intStatus = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
checkInterrupts(ThreadContext *tc) const
|
||||
{
|
||||
return intStatus;
|
||||
}
|
||||
|
||||
Fault
|
||||
getInterrupt(ThreadContext *tc)
|
||||
{
|
||||
warn_once("ARM Interrupts not handled\n");
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
void
|
||||
updateIntrInfo(ThreadContext *tc)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
serialize(std::ostream &os)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace ARM_ISA
|
||||
|
||||
#endif // __ARCH_ARM_INTERRUPT_HH__
|
337
src/arch/arm/intregs.hh
Normal file
337
src/arch/arm/intregs.hh
Normal 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
|
|
@ -44,6 +44,38 @@ namespace ArmISA
|
|||
{
|
||||
protected:
|
||||
MiscReg miscRegs[NumMiscRegs];
|
||||
const IntRegIndex *intRegMap;
|
||||
|
||||
void
|
||||
updateRegMap(CPSR cpsr)
|
||||
{
|
||||
switch (cpsr.mode) {
|
||||
case MODE_USER:
|
||||
case MODE_SYSTEM:
|
||||
intRegMap = IntRegUsrMap;
|
||||
break;
|
||||
case MODE_FIQ:
|
||||
intRegMap = IntRegFiqMap;
|
||||
break;
|
||||
case MODE_IRQ:
|
||||
intRegMap = IntRegIrqMap;
|
||||
break;
|
||||
case MODE_SVC:
|
||||
intRegMap = IntRegSvcMap;
|
||||
break;
|
||||
case MODE_MON:
|
||||
intRegMap = IntRegMonMap;
|
||||
break;
|
||||
case MODE_ABORT:
|
||||
intRegMap = IntRegAbtMap;
|
||||
break;
|
||||
case MODE_UNDEFINED:
|
||||
intRegMap = IntRegUndMap;
|
||||
break;
|
||||
default:
|
||||
panic("Unrecognized mode setting in CPSR.\n");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void clear()
|
||||
|
@ -52,6 +84,15 @@ namespace ArmISA
|
|||
CPSR cpsr = 0;
|
||||
cpsr.mode = MODE_USER;
|
||||
miscRegs[MISCREG_CPSR] = cpsr;
|
||||
updateRegMap(cpsr);
|
||||
|
||||
SCTLR sctlr = 0;
|
||||
sctlr.nmfi = 1;
|
||||
sctlr.rao1 = 1;
|
||||
sctlr.rao2 = 1;
|
||||
sctlr.rao3 = 1;
|
||||
sctlr.rao4 = 1;
|
||||
|
||||
//XXX We need to initialize the rest of the state.
|
||||
}
|
||||
|
||||
|
@ -59,34 +100,94 @@ namespace ArmISA
|
|||
readMiscRegNoEffect(int misc_reg)
|
||||
{
|
||||
assert(misc_reg < NumMiscRegs);
|
||||
if (misc_reg == MISCREG_SPSR) {
|
||||
CPSR cpsr = miscRegs[MISCREG_CPSR];
|
||||
switch (cpsr.mode) {
|
||||
case MODE_USER:
|
||||
return miscRegs[MISCREG_SPSR];
|
||||
case MODE_FIQ:
|
||||
return miscRegs[MISCREG_SPSR_FIQ];
|
||||
case MODE_IRQ:
|
||||
return miscRegs[MISCREG_SPSR_IRQ];
|
||||
case MODE_SVC:
|
||||
return miscRegs[MISCREG_SPSR_SVC];
|
||||
case MODE_MON:
|
||||
return miscRegs[MISCREG_SPSR_MON];
|
||||
case MODE_ABORT:
|
||||
return miscRegs[MISCREG_SPSR_ABT];
|
||||
case MODE_UNDEFINED:
|
||||
return miscRegs[MISCREG_SPSR_UND];
|
||||
default:
|
||||
return miscRegs[MISCREG_SPSR];
|
||||
}
|
||||
}
|
||||
return miscRegs[misc_reg];
|
||||
}
|
||||
|
||||
MiscReg
|
||||
readMiscReg(int misc_reg, ThreadContext *tc)
|
||||
{
|
||||
assert(misc_reg < NumMiscRegs);
|
||||
return miscRegs[misc_reg];
|
||||
return readMiscRegNoEffect(misc_reg);
|
||||
}
|
||||
|
||||
void
|
||||
setMiscRegNoEffect(int misc_reg, const MiscReg &val)
|
||||
{
|
||||
assert(misc_reg < NumMiscRegs);
|
||||
if (misc_reg == MISCREG_SPSR) {
|
||||
CPSR cpsr = miscRegs[MISCREG_CPSR];
|
||||
switch (cpsr.mode) {
|
||||
case MODE_USER:
|
||||
miscRegs[MISCREG_SPSR] = val;
|
||||
return;
|
||||
case MODE_FIQ:
|
||||
miscRegs[MISCREG_SPSR_FIQ] = val;
|
||||
return;
|
||||
case MODE_IRQ:
|
||||
miscRegs[MISCREG_SPSR_IRQ] = val;
|
||||
return;
|
||||
case MODE_SVC:
|
||||
miscRegs[MISCREG_SPSR_SVC] = val;
|
||||
return;
|
||||
case MODE_MON:
|
||||
miscRegs[MISCREG_SPSR_MON] = val;
|
||||
return;
|
||||
case MODE_ABORT:
|
||||
miscRegs[MISCREG_SPSR_ABT] = val;
|
||||
return;
|
||||
case MODE_UNDEFINED:
|
||||
miscRegs[MISCREG_SPSR_UND] = val;
|
||||
return;
|
||||
default:
|
||||
miscRegs[MISCREG_SPSR] = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
miscRegs[misc_reg] = val;
|
||||
}
|
||||
|
||||
void
|
||||
setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||
{
|
||||
assert(misc_reg < NumMiscRegs);
|
||||
miscRegs[misc_reg] = val;
|
||||
if (misc_reg == MISCREG_CPSR) {
|
||||
updateRegMap(val);
|
||||
}
|
||||
return setMiscRegNoEffect(misc_reg, val);
|
||||
}
|
||||
|
||||
int
|
||||
flattenIntIndex(int reg)
|
||||
{
|
||||
return reg;
|
||||
assert(reg >= 0);
|
||||
if (reg < NUM_ARCH_INTREGS) {
|
||||
return intRegMap[reg];
|
||||
} else if (reg < NUM_INTREGS) {
|
||||
return reg;
|
||||
} else {
|
||||
reg -= NUM_INTREGS;
|
||||
assert(reg < NUM_ARCH_INTREGS);
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -95,9 +196,10 @@ namespace ArmISA
|
|||
return reg;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
void serialize(EventManager *em, std::ostream &os)
|
||||
{}
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string §ion)
|
||||
{}
|
||||
|
||||
ISA()
|
||||
|
|
|
@ -38,14 +38,18 @@ def bitfield ENCODING encoding;
|
|||
def bitfield OPCODE opcode;
|
||||
def bitfield MEDIA_OPCODE mediaOpcode;
|
||||
def bitfield MEDIA_OPCODE2 mediaOpcode2;
|
||||
def bitfield USEIMM useImm;
|
||||
def bitfield OPCODE_24 opcode24;
|
||||
def bitfield OPCODE_23_20 opcode23_20;
|
||||
def bitfield OPCODE_23_21 opcode23_21;
|
||||
def bitfield OPCODE_22 opcode22;
|
||||
def bitfield OPCODE_20 opcode20;
|
||||
def bitfield OPCODE_19 opcode19;
|
||||
def bitfield OPCODE_18 opcode18;
|
||||
def bitfield OPCODE_15_12 opcode15_12;
|
||||
def bitfield OPCODE_15 opcode15;
|
||||
def bitfield MISC_OPCODE miscOpcode;
|
||||
def bitfield OPC2 opc2;
|
||||
def bitfield OPCODE_7 opcode7;
|
||||
def bitfield OPCODE_4 opcode4;
|
||||
|
||||
|
|
|
@ -51,20 +51,25 @@ format DataOp {
|
|||
resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
|
||||
Rd = (uint32_t)(resTemp & 0xffffffff);
|
||||
Rn = (uint32_t)(resTemp >> 32);
|
||||
}});
|
||||
0x5: WarnUnimpl::smlal();
|
||||
}}, llbit);
|
||||
0x5: smlal({{
|
||||
resTemp = ((int64_t)Rm) * ((int64_t)Rs);
|
||||
resTemp += (((uint64_t)Rn) << 32) | ((uint64_t)Rd);
|
||||
Rd = (uint32_t)(resTemp & 0xffffffff);
|
||||
Rn = (uint32_t)(resTemp >> 32);
|
||||
}}, llbit);
|
||||
0x6: smull({{
|
||||
resTemp = ((int64_t)(int32_t)Rm)*
|
||||
((int64_t)(int32_t)Rs);
|
||||
Rd = (int32_t)(resTemp & 0xffffffff);
|
||||
Rn = (int32_t)(resTemp >> 32);
|
||||
}});
|
||||
}}, llbit);
|
||||
0x7: umlal({{
|
||||
resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
|
||||
resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd);
|
||||
Rd = (uint32_t)(resTemp & 0xffffffff);
|
||||
Rn = (uint32_t)(resTemp >> 32);
|
||||
}});
|
||||
}}, llbit);
|
||||
}
|
||||
1: decode PUBWL {
|
||||
0x10: WarnUnimpl::swp();
|
||||
|
@ -91,9 +96,9 @@ format DataOp {
|
|||
0x2: sub({{ Rd = resTemp = Rn - op2; }}, sub);
|
||||
0x3: rsb({{ Rd = resTemp = op2 - Rn; }}, rsb);
|
||||
0x4: add({{ Rd = resTemp = Rn + op2; }}, add);
|
||||
0x5: adc({{ Rd = resTemp = Rn + op2 + Cpsr<29:>; }}, add);
|
||||
0x6: sbc({{ Rd = resTemp = Rn - op2 - !Cpsr<29:>; }}, sub);
|
||||
0x7: rsc({{ Rd = resTemp = op2 - Rn - !Cpsr<29:>; }}, rsb);
|
||||
0x5: adc({{ Rd = resTemp = Rn + op2 + CondCodes<29:>; }}, add);
|
||||
0x6: sbc({{ Rd = resTemp = Rn - op2 - !CondCodes<29:>; }}, sub);
|
||||
0x7: rsc({{ Rd = resTemp = op2 - Rn - !CondCodes<29:>; }}, rsb);
|
||||
0x8: tst({{ resTemp = Rn & op2; }});
|
||||
0x9: teq({{ resTemp = Rn ^ op2; }});
|
||||
0xa: cmp({{ resTemp = Rn - op2; }}, sub);
|
||||
|
@ -105,10 +110,37 @@ format DataOp {
|
|||
}
|
||||
1: decode MISC_OPCODE {
|
||||
0x0: decode OPCODE {
|
||||
0x8: WarnUnimpl::mrs_cpsr();
|
||||
0x9: WarnUnimpl::msr_cpsr();
|
||||
0xa: WarnUnimpl::mrs_spsr();
|
||||
0xb: WarnUnimpl::msr_spsr();
|
||||
0x8: PredOp::mrs_cpsr({{
|
||||
Rd = (Cpsr | CondCodes) & 0xF8FF03DF;
|
||||
}});
|
||||
0x9: decode USEIMM {
|
||||
// The mask field is the same as the RN index.
|
||||
0: PredOp::msr_cpsr_reg({{
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(Cpsr | CondCodes,
|
||||
Rm, RN, false);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
}});
|
||||
1: PredImmOp::msr_cpsr_imm({{
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(Cpsr | CondCodes,
|
||||
rotated_imm, RN, false);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
}});
|
||||
}
|
||||
0xa: PredOp::mrs_spsr({{ Rd = Spsr; }});
|
||||
0xb: decode USEIMM {
|
||||
// The mask field is the same as the RN index.
|
||||
0: PredOp::msr_spsr_reg({{
|
||||
Spsr = spsrWriteByInstr(Spsr, Rm, RN, false);
|
||||
}});
|
||||
1: PredImmOp::msr_spsr_imm({{
|
||||
Spsr = spsrWriteByInstr(Spsr, rotated_imm,
|
||||
RN, false);
|
||||
}});
|
||||
}
|
||||
}
|
||||
0x1: decode OPCODE {
|
||||
0x9: BranchExchange::bx({{ }});
|
||||
|
@ -129,28 +161,32 @@ format DataOp {
|
|||
0xb: WarnUnimpl::qdsub();
|
||||
}
|
||||
0x8: decode OPCODE {
|
||||
0x8: WarnUnimpl::smlabb();
|
||||
0x8: smlabb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>) + Rd; }}, overflow);
|
||||
0x9: WarnUnimpl::smlalbb();
|
||||
0xa: WarnUnimpl::smlawb();
|
||||
0xb: WarnUnimpl::smulbb();
|
||||
0xb: smulbb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>); }}, none);
|
||||
}
|
||||
0xa: decode OPCODE {
|
||||
0x8: WarnUnimpl::smlatb();
|
||||
0x9: WarnUnimpl::smulwb();
|
||||
0x8: smlatb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>) + Rd; }}, overflow);
|
||||
0x9: smulwb({{
|
||||
Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<15:0>), 47, 16);
|
||||
}}, none);
|
||||
0xa: WarnUnimpl::smlaltb();
|
||||
0xb: WarnUnimpl::smultb();
|
||||
0xb: smultb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>); }}, none);
|
||||
}
|
||||
0xc: decode OPCODE {
|
||||
0x8: WarnUnimpl::smlabt();
|
||||
0x8: smlabt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>) + Rd; }}, overflow);
|
||||
0x9: WarnUnimpl::smlawt();
|
||||
0xa: WarnUnimpl::smlalbt();
|
||||
0xb: WarnUnimpl::smulbt();
|
||||
0xb: smulbt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>); }}, none);
|
||||
}
|
||||
0xe: decode OPCODE {
|
||||
0x8: WarnUnimpl::smlatt();
|
||||
0x9: WarnUnimpl::smulwt();
|
||||
0x8: smlatt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>) + Rd; }}, overflow);
|
||||
0x9: smulwt({{
|
||||
Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<31:16>), 47, 16);
|
||||
}}, none);
|
||||
0xa: WarnUnimpl::smlaltt();
|
||||
0xb: WarnUnimpl::smultt();
|
||||
0xb: smultt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>); }}, none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,9 +199,15 @@ format DataOp {
|
|||
0x2: subi({{ Rd = resTemp = Rn - rotated_imm; }}, sub);
|
||||
0x3: rsbi({{ Rd = resTemp = rotated_imm - Rn; }}, rsb);
|
||||
0x4: addi({{ Rd = resTemp = Rn + rotated_imm; }}, add);
|
||||
0x5: adci({{ Rd = resTemp = Rn + rotated_imm + Cpsr<29:>; }}, add);
|
||||
0x6: sbci({{ Rd = resTemp = Rn -rotated_imm - !Cpsr<29:>; }}, sub);
|
||||
0x7: rsci({{ Rd = resTemp = rotated_imm - Rn - !Cpsr<29:>;}}, rsb);
|
||||
0x5: adci({{
|
||||
Rd = resTemp = Rn + rotated_imm + CondCodes<29:>;
|
||||
}}, add);
|
||||
0x6: sbci({{
|
||||
Rd = resTemp = Rn -rotated_imm - !CondCodes<29:>;
|
||||
}}, sub);
|
||||
0x7: rsci({{
|
||||
Rd = resTemp = rotated_imm - Rn - !CondCodes<29:>;
|
||||
}}, rsb);
|
||||
0x8: tsti({{ resTemp = Rn & rotated_imm; }});
|
||||
0x9: teqi({{ resTemp = Rn ^ rotated_imm; }});
|
||||
0xa: cmpi({{ resTemp = Rn - rotated_imm; }}, sub);
|
||||
|
@ -178,11 +220,27 @@ format DataOp {
|
|||
}
|
||||
1: decode OPCODE {
|
||||
// The following two instructions aren't supposed to be defined
|
||||
0x8: WarnUnimpl::undefined_instruction();
|
||||
0x9: WarnUnimpl::undefined_instruction();
|
||||
|
||||
0xa: WarnUnimpl::mrs_i_cpsr();
|
||||
0xb: WarnUnimpl::mrs_i_spsr();
|
||||
0x8: DataOp::movw({{ Rd = IMMED_11_0 | (RN << 12) ; }});
|
||||
0x9: decode RN {
|
||||
0: decode IMM {
|
||||
0: PredImmOp::nop({{ ; }});
|
||||
1: WarnUnimpl::yield();
|
||||
2: WarnUnimpl::wfe();
|
||||
3: WarnUnimpl::wfi();
|
||||
4: WarnUnimpl::sev();
|
||||
}
|
||||
default: PredImmOp::msr_i_cpsr({{
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(Cpsr | CondCodes,
|
||||
rotated_imm, RN, false);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
}});
|
||||
}
|
||||
0xa: PredOp::movt({{ Rd = IMMED_11_0 << 16 | RN << 28 | Rd<15:0>; }});
|
||||
0xb: PredImmOp::msr_i_spsr({{
|
||||
Spsr = spsrWriteByInstr(Spsr, rotated_imm, RN, false);
|
||||
}});
|
||||
}
|
||||
}
|
||||
0x2: AddrMode2::addrMode2(Disp, disp);
|
||||
|
@ -324,77 +382,79 @@ format DataOp {
|
|||
}
|
||||
}
|
||||
0x7: decode OPCODE_24 {
|
||||
0: decode CPNUM {
|
||||
// Coprocessor Instructions
|
||||
0x1: decode OPCODE_4 {
|
||||
0: decode OPCODE_4 {
|
||||
0: decode CPNUM {
|
||||
format FloatOp {
|
||||
// Basic FPA Instructions
|
||||
0: decode OPCODE_23_20 {
|
||||
0x0: decode OPCODE_15 {
|
||||
0: adf({{ Fd.sf = Fn.sf + Fm.sf; }});
|
||||
1: mvf({{ Fd.sf = Fm.sf; }});
|
||||
}
|
||||
0x1: decode OPCODE_15 {
|
||||
0: muf({{ Fd.sf = Fn.sf * Fm.sf; }});
|
||||
1: mnf({{ Fd.sf = -Fm.sf; }});
|
||||
}
|
||||
0x2: decode OPCODE_15 {
|
||||
0: suf({{ Fd.sf = Fn.sf - Fm.sf; }});
|
||||
1: abs({{ Fd.sf = fabs(Fm.sf); }});
|
||||
}
|
||||
0x3: decode OPCODE_15 {
|
||||
0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }});
|
||||
1: rnd({{ Fd.sf = rint(Fm.sf); }});
|
||||
}
|
||||
0x4: decode OPCODE_15 {
|
||||
0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }});
|
||||
1: sqt({{ Fd.sf = sqrt(Fm.sf); }});
|
||||
}
|
||||
0x5: decode OPCODE_15 {
|
||||
0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }});
|
||||
1: log({{ Fd.sf = log10(Fm.sf); }});
|
||||
}
|
||||
0x6: decode OPCODE_15 {
|
||||
0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }});
|
||||
1: lgn({{ Fd.sf = log(Fm.sf); }});
|
||||
}
|
||||
0x7: decode OPCODE_15 {
|
||||
0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }});
|
||||
1: exp({{ Fd.sf = exp(Fm.sf); }});
|
||||
}
|
||||
0x8: decode OPCODE_15 {
|
||||
0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }});
|
||||
1: sin({{ Fd.sf = sin(Fm.sf); }});
|
||||
}
|
||||
0x9: decode OPCODE_15 {
|
||||
0: fml({{ Fd.sf = Fn.sf * Fm.sf; }});
|
||||
1: cos({{ Fd.sf = cos(Fm.sf); }});
|
||||
}
|
||||
0xa: decode OPCODE_15 {
|
||||
0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }});
|
||||
1: tan({{ Fd.sf = tan(Fm.sf); }});
|
||||
}
|
||||
0xb: decode OPCODE_15 {
|
||||
0: frd({{ Fd.sf = Fm.sf / Fn.sf; }});
|
||||
1: asn({{ Fd.sf = asin(Fm.sf); }});
|
||||
}
|
||||
0xc: decode OPCODE_15 {
|
||||
0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }});
|
||||
1: acs({{ Fd.sf = acos(Fm.sf); }});
|
||||
}
|
||||
0xd: decode OPCODE_15 {
|
||||
1: atn({{ Fd.sf = atan(Fm.sf); }});
|
||||
}
|
||||
0xe: decode OPCODE_15 {
|
||||
// Unnormalised Round
|
||||
1: FailUnimpl::urd();
|
||||
}
|
||||
0xf: decode OPCODE_15 {
|
||||
// Normalise
|
||||
1: FailUnimpl::nrm();
|
||||
}
|
||||
}
|
||||
1: decode OPCODE_15_12 {
|
||||
0x1: decode OPCODE_23_20 {
|
||||
0x0: decode OPCODE_15 {
|
||||
0: adf({{ Fd.sf = Fn.sf + Fm.sf; }});
|
||||
1: mvf({{ Fd.sf = Fm.sf; }});
|
||||
}
|
||||
0x1: decode OPCODE_15 {
|
||||
0: muf({{ Fd.sf = Fn.sf * Fm.sf; }});
|
||||
1: mnf({{ Fd.sf = -Fm.sf; }});
|
||||
}
|
||||
0x2: decode OPCODE_15 {
|
||||
0: suf({{ Fd.sf = Fn.sf - Fm.sf; }});
|
||||
1: abs({{ Fd.sf = fabs(Fm.sf); }});
|
||||
}
|
||||
0x3: decode OPCODE_15 {
|
||||
0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }});
|
||||
1: rnd({{ Fd.sf = rint(Fm.sf); }});
|
||||
}
|
||||
0x4: decode OPCODE_15 {
|
||||
0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }});
|
||||
1: sqt({{ Fd.sf = sqrt(Fm.sf); }});
|
||||
}
|
||||
0x5: decode OPCODE_15 {
|
||||
0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }});
|
||||
1: log({{ Fd.sf = log10(Fm.sf); }});
|
||||
}
|
||||
0x6: decode OPCODE_15 {
|
||||
0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }});
|
||||
1: lgn({{ Fd.sf = log(Fm.sf); }});
|
||||
}
|
||||
0x7: decode OPCODE_15 {
|
||||
0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }});
|
||||
1: exp({{ Fd.sf = exp(Fm.sf); }});
|
||||
}
|
||||
0x8: decode OPCODE_15 {
|
||||
0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }});
|
||||
1: sin({{ Fd.sf = sin(Fm.sf); }});
|
||||
}
|
||||
0x9: decode OPCODE_15 {
|
||||
0: fml({{ Fd.sf = Fn.sf * Fm.sf; }});
|
||||
1: cos({{ Fd.sf = cos(Fm.sf); }});
|
||||
}
|
||||
0xa: decode OPCODE_15 {
|
||||
0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }});
|
||||
1: tan({{ Fd.sf = tan(Fm.sf); }});
|
||||
}
|
||||
0xb: decode OPCODE_15 {
|
||||
0: frd({{ Fd.sf = Fm.sf / Fn.sf; }});
|
||||
1: asn({{ Fd.sf = asin(Fm.sf); }});
|
||||
}
|
||||
0xc: decode OPCODE_15 {
|
||||
0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }});
|
||||
1: acs({{ Fd.sf = acos(Fm.sf); }});
|
||||
}
|
||||
0xd: decode OPCODE_15 {
|
||||
1: atn({{ Fd.sf = atan(Fm.sf); }});
|
||||
}
|
||||
0xe: decode OPCODE_15 {
|
||||
// Unnormalised Round
|
||||
1: FailUnimpl::urd();
|
||||
}
|
||||
0xf: decode OPCODE_15 {
|
||||
// Normalise
|
||||
1: FailUnimpl::nrm();
|
||||
}
|
||||
} // OPCODE_23_20
|
||||
} // format FloatOp
|
||||
} // CPNUM
|
||||
1: decode CPNUM { // 27-24=1110,4 ==1
|
||||
1: decode OPCODE_15_12 {
|
||||
format FloatOp {
|
||||
0xf: decode OPCODE_23_21 {
|
||||
format FloatCmp {
|
||||
0x4: cmf({{ Fn.df }}, {{ Fm.df }});
|
||||
|
@ -417,36 +477,86 @@ format DataOp {
|
|||
0x4: FailUnimpl::wfc();
|
||||
0x5: FailUnimpl::rfc();
|
||||
}
|
||||
}
|
||||
} // format FloatOp
|
||||
}
|
||||
}
|
||||
0xa: decode MISC_OPCODE {
|
||||
0x1: decode MEDIA_OPCODE {
|
||||
0xf: decode RN {
|
||||
0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }});
|
||||
0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }});
|
||||
0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }});
|
||||
0xa: decode MISC_OPCODE {
|
||||
0x1: decode MEDIA_OPCODE {
|
||||
0xf: decode RN {
|
||||
0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }});
|
||||
0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }});
|
||||
0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }});
|
||||
}
|
||||
0xe: decode RN {
|
||||
0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }});
|
||||
0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }});
|
||||
0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }});
|
||||
}
|
||||
} // MEDIA_OPCODE (MISC_OPCODE 0x1)
|
||||
} // MISC_OPCODE (CPNUM 0xA)
|
||||
0xf: decode RN {
|
||||
// Barrriers, Cache Maintence, NOPS
|
||||
7: decode OPCODE_23_21 {
|
||||
0: decode RM {
|
||||
0: decode OPC2 {
|
||||
4: decode OPCODE_20 {
|
||||
0: PredOp::mcr_cp15_nop1({{ }}); // was wfi
|
||||
}
|
||||
}
|
||||
1: WarnUnimpl::cp15_cache_maint();
|
||||
4: WarnUnimpl::cp15_par();
|
||||
5: decode OPC2 {
|
||||
0,1: WarnUnimpl::cp15_cache_maint2();
|
||||
4: PredOp::cp15_isb({{ ; }}, IsMemBarrier, IsSerializeBefore);
|
||||
6,7: WarnUnimpl::cp15_bp_maint();
|
||||
}
|
||||
6: WarnUnimpl::cp15_cache_maint3();
|
||||
8: WarnUnimpl::cp15_va_to_pa();
|
||||
10: decode OPC2 {
|
||||
1,2: WarnUnimpl::cp15_cache_maint3();
|
||||
4: PredOp::cp15_dsb({{ ; }}, IsMemBarrier, IsSerializeBefore);
|
||||
5: PredOp::cp15_dmb({{ ; }}, IsMemBarrier, IsSerializeBefore);
|
||||
}
|
||||
11: WarnUnimpl::cp15_cache_maint4();
|
||||
13: decode OPC2 {
|
||||
1: decode OPCODE_20 {
|
||||
0: PredOp::mcr_cp15_nop2({{ }}); // was prefetch
|
||||
}
|
||||
}
|
||||
14: WarnUnimpl::cp15_cache_maint5();
|
||||
} // RM
|
||||
} // OPCODE_23_21 CR
|
||||
|
||||
// Thread ID and context ID registers
|
||||
// Thread ID register needs cheaper access than miscreg
|
||||
13: WarnUnimpl::mcr_mrc_cp15_c7();
|
||||
|
||||
// All the rest
|
||||
default: decode OPCODE_20 {
|
||||
0: PredOp::mcr_cp15({{
|
||||
fault = setCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2);
|
||||
}});
|
||||
1: PredOp::mrc_cp15({{
|
||||
fault = readCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2);
|
||||
}});
|
||||
}
|
||||
0xe: decode RN {
|
||||
0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }});
|
||||
0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }});
|
||||
0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }});
|
||||
}
|
||||
}
|
||||
} // RN
|
||||
} // CPNUM (OP4 == 1)
|
||||
} //OPCODE_4
|
||||
|
||||
#if FULL_SYSTEM
|
||||
1: PredOp::swi({{ fault = new SupervisorCall; }}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
|
||||
#else
|
||||
1: PredOp::swi({{ if (testPredicate(CondCodes, condCode))
|
||||
{
|
||||
if (IMMED_23_0)
|
||||
xc->syscall(IMMED_23_0);
|
||||
else
|
||||
xc->syscall(R7);
|
||||
}
|
||||
}
|
||||
format PredOp {
|
||||
// ARM System Call (SoftWare Interrupt)
|
||||
1: swi({{ if (testPredicate(Cpsr, condCode))
|
||||
{
|
||||
if (IMMED_23_0)
|
||||
xc->syscall(IMMED_23_0);
|
||||
else
|
||||
xc->syscall(R7);
|
||||
}
|
||||
}});
|
||||
}
|
||||
}
|
||||
}});
|
||||
#endif // FULL_SYSTEM
|
||||
} // OPCODE_24
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ def format Branch(code,*opt_flags) {{
|
|||
else:
|
||||
inst_flags += ('IsCondControl', )
|
||||
|
||||
icode = 'if (testPredicate(Cpsr, condCode)) {\n'
|
||||
icode = 'if (testPredicate(CondCodes, condCode)) {\n'
|
||||
icode += code
|
||||
icode += ' NPC = NPC + 4 + disp;\n'
|
||||
icode += '} else {\n'
|
||||
|
@ -90,7 +90,7 @@ def format BranchExchange(code,*opt_flags) {{
|
|||
|
||||
#Condition code
|
||||
|
||||
icode = 'if (testPredicate(Cpsr, condCode)) {\n'
|
||||
icode = 'if (testPredicate(CondCodes, condCode)) {\n'
|
||||
icode += code
|
||||
icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n'
|
||||
icode += '} else {\n'
|
||||
|
|
|
@ -119,8 +119,8 @@ let {{
|
|||
_ic = %(fReg1)s >= %(fReg2)s;
|
||||
_iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1;
|
||||
|
||||
Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
|
||||
(Cpsr & 0x0FFFFFFF);
|
||||
CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
|
||||
(CondCodes & 0x0FFFFFFF);
|
||||
'''
|
||||
}};
|
||||
|
||||
|
|
|
@ -72,6 +72,18 @@ let {{
|
|||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
microLdrRetUopCode = '''
|
||||
Ra = Mem;
|
||||
Cpsr = cpsrWriteByInstr(Cpsr, Spsr, 0xF, true);
|
||||
'''
|
||||
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
|
||||
'MicroMemOp',
|
||||
{'memacc_code': microLdrRetUopCode,
|
||||
'ea_code':
|
||||
'EA = Rb + (UP ? imm : -imm);',
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
|
||||
'MicroMemOp',
|
||||
{'memacc_code': 'Mem = Ra;',
|
||||
|
@ -80,14 +92,19 @@ let {{
|
|||
['IsMicroop'])
|
||||
|
||||
header_output = MicroMemDeclare.subst(microLdrUopIop) + \
|
||||
MicroMemDeclare.subst(microLdrRetUopIop) + \
|
||||
MicroMemDeclare.subst(microStrUopIop)
|
||||
decoder_output = MicroConstructor.subst(microLdrUopIop) + \
|
||||
MicroConstructor.subst(microLdrRetUopIop) + \
|
||||
MicroConstructor.subst(microStrUopIop)
|
||||
exec_output = LoadExecute.subst(microLdrUopIop) + \
|
||||
LoadExecute.subst(microLdrRetUopIop) + \
|
||||
StoreExecute.subst(microStrUopIop) + \
|
||||
LoadInitiateAcc.subst(microLdrUopIop) + \
|
||||
LoadInitiateAcc.subst(microLdrRetUopIop) + \
|
||||
StoreInitiateAcc.subst(microStrUopIop) + \
|
||||
LoadCompleteAcc.subst(microLdrUopIop) + \
|
||||
LoadCompleteAcc.subst(microLdrRetUopIop) + \
|
||||
StoreCompleteAcc.subst(microStrUopIop)
|
||||
}};
|
||||
|
||||
|
@ -178,73 +195,64 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
|||
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
|
||||
{
|
||||
%(constructor)s;
|
||||
uint32_t regs_to_handle = reglist;
|
||||
uint32_t start_addr = 0;
|
||||
uint32_t regs = reglist;
|
||||
uint32_t addr = 0;
|
||||
bool up = machInst.puswl.up;
|
||||
|
||||
switch (puswl)
|
||||
{
|
||||
case 0x00: // stmda
|
||||
case 0x01: // L ldmda_l
|
||||
case 0x02: // W stmda_w
|
||||
case 0x03: // WL ldmda_wl
|
||||
start_addr = (ones << 2) - 4;
|
||||
break;
|
||||
case 0x08: // U stmia_u
|
||||
case 0x09: // U L ldmia_ul
|
||||
case 0x0a: // U W stmia
|
||||
case 0x0b: // U WL ldmia
|
||||
start_addr = 0;
|
||||
break;
|
||||
case 0x10: // P stmdb
|
||||
case 0x11: // P L ldmdb
|
||||
case 0x12: // P W stmdb
|
||||
case 0x13: // P WL ldmdb
|
||||
start_addr = (ones << 2); // U-bit is already 0 for subtract
|
||||
break;
|
||||
case 0x18: // PU stmib
|
||||
case 0x19: // PU L ldmib
|
||||
case 0x1a: // PU W stmib
|
||||
case 0x1b: // PU WL ldmib
|
||||
start_addr = 4;
|
||||
break;
|
||||
default:
|
||||
panic("Unhandled Load/Store Multiple Instruction, "
|
||||
"puswl = 0x%x", (unsigned) puswl);
|
||||
break;
|
||||
}
|
||||
if (!up)
|
||||
addr = (ones << 2) - 4;
|
||||
|
||||
// Add 0 to Rn and stick it in Raddr (register 17).
|
||||
if (machInst.puswl.prepost)
|
||||
addr += 4;
|
||||
|
||||
// Add 0 to Rn and stick it in ureg0.
|
||||
// This is equivalent to a move.
|
||||
microOps[0] = new MicroAddiUop(machInst, 17, RN, 0);
|
||||
microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
|
||||
|
||||
unsigned j = 0;
|
||||
for (int i = 1; i < ones+1; i++) {
|
||||
// Get next available bit for transfer
|
||||
while (! ( regs_to_handle & (1<<j)))
|
||||
j++;
|
||||
regs_to_handle &= ~(1<<j);
|
||||
unsigned reg = 0;
|
||||
bool force_user = machInst.puswl.psruser & !OPCODE_15;
|
||||
bool exception_ret = machInst.puswl.psruser & OPCODE_15;
|
||||
|
||||
if (loadop)
|
||||
microOps[i] = new MicroLdrUop(machInst, j, 17, start_addr);
|
||||
else
|
||||
microOps[i] = new MicroStrUop(machInst, j, 17, start_addr);
|
||||
for (int i = 1; i < ones + 1; i++) {
|
||||
// Find the next register.
|
||||
while (!bits(regs, reg))
|
||||
reg++;
|
||||
replaceBits(regs, reg, 0);
|
||||
|
||||
unsigned regIdx = reg;
|
||||
if (force_user) {
|
||||
regIdx = intRegForceUser(regIdx);
|
||||
}
|
||||
|
||||
if (machInst.puswl.loadOp) {
|
||||
if (reg == INTREG_PC && exception_ret) {
|
||||
// This must be the exception return form of ldm.
|
||||
microOps[i] =
|
||||
new MicroLdrRetUop(machInst, regIdx, INTREG_UREG0, addr);
|
||||
} else {
|
||||
microOps[i] =
|
||||
new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr);
|
||||
}
|
||||
} else {
|
||||
microOps[i] =
|
||||
new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr);
|
||||
}
|
||||
|
||||
if (up)
|
||||
start_addr += 4;
|
||||
addr += 4;
|
||||
else
|
||||
start_addr -= 4;
|
||||
addr -= 4;
|
||||
}
|
||||
|
||||
if (writeback) {
|
||||
StaticInstPtr &lastUop = microOps[numMicroops - 1];
|
||||
if (machInst.puswl.writeback) {
|
||||
if (up) {
|
||||
microOps[numMicroops-1] =
|
||||
new MicroAddiUop(machInst, RN, RN, ones * 4);
|
||||
lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
|
||||
} else {
|
||||
microOps[numMicroops-1] =
|
||||
new MicroSubiUop(machInst, RN, RN, ones * 4);
|
||||
lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
|
||||
}
|
||||
}
|
||||
microOps[numMicroops-1]->setLastMicroop();
|
||||
lastUop->setLastMicroop();
|
||||
}
|
||||
|
||||
}};
|
||||
|
@ -285,14 +293,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
|||
if (writeback)
|
||||
{
|
||||
if (up) {
|
||||
microOps[numMicroops-1] =
|
||||
microOps[numMicroops - 1] =
|
||||
new MicroAddiUop(machInst, RN, RN, disp8);
|
||||
} else {
|
||||
microOps[numMicroops-1] =
|
||||
microOps[numMicroops - 1] =
|
||||
new MicroSubiUop(machInst, RN, RN, disp8);
|
||||
}
|
||||
}
|
||||
microOps[numMicroops-1]->setLastMicroop();
|
||||
microOps[numMicroops - 1]->setLastMicroop();
|
||||
}
|
||||
|
||||
}};
|
||||
|
@ -316,14 +324,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
|||
|
||||
if (writeback) {
|
||||
if (up) {
|
||||
microOps[numMicroops-1] =
|
||||
microOps[numMicroops - 1] =
|
||||
new MicroAddiUop(machInst, RN, RN, disp8);
|
||||
} else {
|
||||
microOps[numMicroops-1] =
|
||||
microOps[numMicroops - 1] =
|
||||
new MicroSubiUop(machInst, RN, RN, disp8);
|
||||
}
|
||||
}
|
||||
microOps[numMicroops-1]->setLastMicroop();
|
||||
microOps[numMicroops - 1]->setLastMicroop();
|
||||
}
|
||||
}};
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
//
|
||||
|
||||
let {{
|
||||
predicateTest = 'testPredicate(Cpsr, condCode)'
|
||||
predicateTest = 'testPredicate(CondCodes, condCode)'
|
||||
}};
|
||||
|
||||
def template PredOpExecute {{
|
||||
|
@ -82,31 +82,44 @@ def template DataImmDecode {{
|
|||
|
||||
let {{
|
||||
|
||||
calcCcCode = '''
|
||||
uint16_t _ic, _iv, _iz, _in;
|
||||
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;
|
||||
|
||||
_in = (resTemp >> 31) & 1;
|
||||
_iz = (resTemp == 0);
|
||||
_iv = %(ivValue)s & 1;
|
||||
_ic = %(icValue)s & 1;
|
||||
CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
|
||||
(CondCodes & 0x0FFFFFFF);
|
||||
|
||||
Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
|
||||
(Cpsr & 0x0FFFFFFF);
|
||||
|
||||
DPRINTF(Arm, "in = %%d\\n", _in);
|
||||
DPRINTF(Arm, "iz = %%d\\n", _iz);
|
||||
DPRINTF(Arm, "ic = %%d\\n", _ic);
|
||||
DPRINTF(Arm, "iv = %%d\\n", _iv);
|
||||
DPRINTF(Arm, "in = %%d\\n", _in);
|
||||
DPRINTF(Arm, "iz = %%d\\n", _iz);
|
||||
DPRINTF(Arm, "ic = %%d\\n", _ic);
|
||||
DPRINTF(Arm, "iv = %%d\\n", _iv);
|
||||
}
|
||||
'''
|
||||
|
||||
}};
|
||||
|
||||
let {{
|
||||
def getCcCode(flagtype):
|
||||
icReg = icImm = iv = ''
|
||||
negBit = 31
|
||||
canOverflow = 'false'
|
||||
|
||||
if flagtype == "none":
|
||||
icReg = icImm = 'Cpsr<29:>'
|
||||
iv = 'Cpsr<28:>'
|
||||
icReg = icImm = 'CondCodes<29:>'
|
||||
iv = 'CondCodes<28:>'
|
||||
elif flagtype == "llbit":
|
||||
icReg = icImm = 'CondCodes<29:>'
|
||||
iv = 'CondCodes<28:>'
|
||||
negBit = 63
|
||||
elif flagtype == "overflow":
|
||||
canOverflow = "true"
|
||||
icReg = icImm = iv = '0'
|
||||
elif flagtype == "add":
|
||||
icReg = icImm = 'findCarry(32, resTemp, Rn, op2)'
|
||||
iv = 'findOverflow(32, resTemp, Rn, op2)'
|
||||
|
@ -117,17 +130,32 @@ let {{
|
|||
icReg = icImm = 'findCarry(32, resTemp, op2, ~Rn)'
|
||||
iv = 'findOverflow(32, resTemp, op2, ~Rn)'
|
||||
else:
|
||||
icReg = 'shift_carry_rs(Rm, Rs, shift, Cpsr<29:>)'
|
||||
icImm = 'shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>)'
|
||||
iv = 'Cpsr<28:>'
|
||||
return (calcCcCode % {"icValue" : icReg, "ivValue" : iv},
|
||||
calcCcCode % {"icValue" : icImm, "ivValue" : iv})
|
||||
icReg = 'shift_carry_rs(Rm, Rs<7:0>, shift, CondCodes<29:>)'
|
||||
icImm = 'shift_carry_imm(Rm, shift_size, shift, CondCodes<29:>)'
|
||||
iv = 'CondCodes<28:>'
|
||||
return (calcCcCode % {"icValue" : icReg,
|
||||
"ivValue" : iv,
|
||||
"negBit" : negBit,
|
||||
"canOverflow" : canOverflow },
|
||||
calcCcCode % {"icValue" : icImm,
|
||||
"ivValue" : iv,
|
||||
"negBit" : negBit,
|
||||
"canOverflow" : canOverflow })
|
||||
|
||||
def getImmCcCode(flagtype):
|
||||
ivValue = icValue = ''
|
||||
negBit = 31
|
||||
canOverflow = 'false'
|
||||
if flagtype == "none":
|
||||
icValue = 'Cpsr<29:>'
|
||||
ivValue = 'Cpsr<28:>'
|
||||
icValue = 'CondCodes<29:>'
|
||||
ivValue = 'CondCodes<28:>'
|
||||
elif flagtype == "llbit":
|
||||
icValue = 'CondCodes<29:>'
|
||||
ivValue = 'CondCodes<28:>'
|
||||
negBit = 63
|
||||
elif flagtype == "overflow":
|
||||
icVaule = ivValue = '0'
|
||||
canOverflow = "true"
|
||||
elif flagtype == "add":
|
||||
icValue = 'findCarry(32, resTemp, Rn, rotated_imm)'
|
||||
ivValue = 'findOverflow(32, resTemp, Rn, rotated_imm)'
|
||||
|
@ -138,18 +166,18 @@ let {{
|
|||
icValue = 'findCarry(32, resTemp, rotated_imm, ~Rn)'
|
||||
ivValue = 'findOverflow(32, resTemp, rotated_imm, ~Rn)'
|
||||
else:
|
||||
icValue = '(rotate ? rotated_carry:Cpsr<29:>)'
|
||||
ivValue = 'Cpsr<28:>'
|
||||
icValue = '(rotate ? rotated_carry:CondCodes<29:>)'
|
||||
ivValue = 'CondCodes<28:>'
|
||||
return calcCcCode % vars()
|
||||
}};
|
||||
|
||||
def format DataOp(code, flagtype = logic) {{
|
||||
(regCcCode, immCcCode) = getCcCode(flagtype)
|
||||
regCode = '''uint32_t op2 = shift_rm_rs(Rm, Rs,
|
||||
shift, Cpsr<29:0>);
|
||||
regCode = '''uint32_t op2 = shift_rm_rs(Rm, Rs<7:0>,
|
||||
shift, CondCodes<29:>);
|
||||
op2 = op2;''' + code
|
||||
immCode = '''uint32_t op2 = shift_rm_imm(Rm, shift_size,
|
||||
shift, Cpsr<29:0>);
|
||||
shift, CondCodes<29:>);
|
||||
op2 = op2;''' + code
|
||||
regIop = InstObjParams(name, Name, 'PredIntOp',
|
||||
{"code": regCode,
|
||||
|
|
|
@ -115,7 +115,7 @@ output exec {{
|
|||
panic("attempt to execute unimplemented instruction '%s' "
|
||||
"(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
|
||||
inst2string(machInst));
|
||||
return new UnimplementedOpcodeFault;
|
||||
return new UnimpFault("Unimplemented Instruction");
|
||||
}
|
||||
|
||||
Fault
|
||||
|
|
|
@ -74,7 +74,7 @@ output exec {{
|
|||
{
|
||||
panic("attempt to execute unknown instruction "
|
||||
"(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst));
|
||||
return new UnimplementedOpcodeFault;
|
||||
return new UnimpFault("Unimplemented Instruction");
|
||||
}
|
||||
}};
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ let {{
|
|||
# Generic substitutions for Arm instructions
|
||||
def ArmGenericCodeSubs(code):
|
||||
# Substitute in the shifted portion of operations
|
||||
new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, Cpsr<29:>)', code)
|
||||
new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code)
|
||||
new_code = re.sub(r'Rm_Imm',
|
||||
'shift_rm_imm(Rm, shift_size, shift, CondCodes<29:>)', code)
|
||||
new_code = re.sub(r'Rm_Rs',
|
||||
'shift_rm_rs(Rm, Rs, shift, CondCodes<29:>)', new_code)
|
||||
return new_code
|
||||
|
||||
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
|
|
|
@ -58,15 +58,16 @@ def operands {{
|
|||
'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite),
|
||||
'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite),
|
||||
'R7': ('IntReg', 'uw', '7', 'IsInteger', 5),
|
||||
'R0': ('IntReg', 'uw', '0', 'IsInteger', 0),
|
||||
|
||||
#Destination register for load/store double instructions
|
||||
'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite),
|
||||
'Rde': ('IntReg', 'uw', '(RD | 1)', 'IsInteger', 5, maybePCRead, maybePCWrite),
|
||||
|
||||
'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 6),
|
||||
'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 7),
|
||||
'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 8),
|
||||
'LR': ('IntReg', 'uw', '14', 'IsInteger', 9),
|
||||
'Rhi': ('IntReg', 'uw', 'INTREG_RHI', 'IsInteger', 7),
|
||||
'Rlo': ('IntReg', 'uw', 'INTREG_RLO', 'IsInteger', 8),
|
||||
'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 9),
|
||||
'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', 'IsInteger', 10),
|
||||
|
||||
#Register fields for microops
|
||||
'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 11, maybePCRead, maybePCWrite),
|
||||
|
@ -80,12 +81,13 @@ def operands {{
|
|||
#Memory Operand
|
||||
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 30),
|
||||
|
||||
'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', 'IsInteger', 40),
|
||||
'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', 'IsInteger', 41),
|
||||
'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', 'IsInteger', 42),
|
||||
'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', 'IsInteger', 43),
|
||||
'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', 'IsInteger', 44),
|
||||
'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 45),
|
||||
'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 46)
|
||||
'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 40),
|
||||
'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', (None, None, 'IsControl'), 41),
|
||||
'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', (None, None, 'IsControl'), 42),
|
||||
'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', (None, None, 'IsControl'), 43),
|
||||
'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', (None, None, 'IsControl'), 44),
|
||||
'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', (None, None, 'IsControl'), 45),
|
||||
'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 50),
|
||||
'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 51)
|
||||
|
||||
}};
|
||||
|
|
|
@ -104,6 +104,8 @@ namespace ArmISA
|
|||
const int WordBytes = 4;
|
||||
const int HalfwordBytes = 2;
|
||||
const int ByteBytes = 1;
|
||||
|
||||
const uint32_t HighVecs = 0xFFFF0000;
|
||||
};
|
||||
|
||||
using namespace ArmISA;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,43 +24,34 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
/*
|
||||
* TypeAST.C
|
||||
*
|
||||
* Description: See TypeAST.hh
|
||||
*
|
||||
* $Id: TypeAST.C,v 3.1 2003/03/22 15:15:16 xu Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_ARM_KERNEL_STATS_HH__
|
||||
#define __ARCH_ARM_KERNEL_STATS_HH__
|
||||
|
||||
#include "mem/slicc/ast/TypeAST.hh"
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
TypeAST::TypeAST(string* ident_ptr)
|
||||
: AST()
|
||||
#include "kern/kernel_stats.hh"
|
||||
|
||||
namespace ArmISA {
|
||||
namespace Kernel {
|
||||
|
||||
enum cpu_mode { hypervisor, kernel, user, idle, cpu_mode_num };
|
||||
extern const char *modestr[];
|
||||
|
||||
class Statistics : public ::Kernel::Statistics
|
||||
{
|
||||
m_ident_ptr = ident_ptr;
|
||||
}
|
||||
public:
|
||||
Statistics(System *system) : ::Kernel::Statistics(system)
|
||||
{}
|
||||
};
|
||||
|
||||
TypeAST::~TypeAST()
|
||||
{
|
||||
delete m_ident_ptr;
|
||||
} /* end namespace ArmISA::Kernel */
|
||||
} /* end namespace ArmISA */
|
||||
|
||||
}
|
||||
|
||||
string TypeAST::toString() const
|
||||
{
|
||||
return *m_ident_ptr;
|
||||
}
|
||||
|
||||
Type* TypeAST::lookupType() const
|
||||
{
|
||||
Type* type_ptr = g_sym_table.getType(*m_ident_ptr);
|
||||
if (type_ptr != NULL) {
|
||||
return type_ptr;
|
||||
} else {
|
||||
error("Type '" + *m_ident_ptr + "' not declared.");
|
||||
}
|
||||
return NULL; // Not reached
|
||||
}
|
||||
#endif // __ARCH_ARM_KERNEL_STATS_HH__
|
|
@ -86,6 +86,7 @@ class ArmLinux : public Linux
|
|||
static const unsigned TIOCISATTY_ = 0x2000745e;
|
||||
static const unsigned TIOCGETS_ = 0x402c7413;
|
||||
static const unsigned TIOCGETA_ = 0x40127417;
|
||||
static const unsigned TCSETAW_ = 0x5407; // 2.6.15 kernel
|
||||
//@}
|
||||
|
||||
/// For table().
|
||||
|
@ -147,6 +148,21 @@ class ArmLinux : public Linux
|
|||
uint64_t st_ino;
|
||||
} tgt_stat64;
|
||||
|
||||
typedef struct {
|
||||
int32_t uptime; /* Seconds since boot */
|
||||
uint32_t loads[3]; /* 1, 5, and 15 minute load averages */
|
||||
uint32_t totalram; /* Total usable main memory size */
|
||||
uint32_t freeram; /* Available memory size */
|
||||
uint32_t sharedram; /* Amount of shared memory */
|
||||
uint32_t bufferram; /* Memory used by buffers */
|
||||
uint32_t totalswap; /* Total swap space size */
|
||||
uint32_t freeswap; /* swap space still available */
|
||||
uint16_t procs; /* Number of current processes */
|
||||
uint32_t totalhigh; /* Total high memory size */
|
||||
uint32_t freehigh; /* Available high memory size */
|
||||
uint32_t mem_unit; /* Memory unit size in bytes */
|
||||
} tgt_sysinfo;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ static SyscallReturn
|
|||
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
|
||||
int index = 0;
|
||||
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
|
||||
|
||||
strcpy(name->sysname, "Linux");
|
||||
strcpy(name->nodename, "m5.eecs.umich.edu");
|
||||
|
@ -179,7 +180,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
|
|||
/* 113 */ SyscallDesc("vm86", unimplementedFunc),
|
||||
/* 114 */ SyscallDesc("wait4", unimplementedFunc),
|
||||
/* 115 */ SyscallDesc("swapoff", unimplementedFunc),
|
||||
/* 116 */ SyscallDesc("sysinfo", unimplementedFunc),
|
||||
/* 116 */ SyscallDesc("sysinfo", sysinfoFunc<ArmLinux>),
|
||||
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
|
||||
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
|
||||
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
|
||||
|
@ -417,7 +418,8 @@ static SyscallReturn
|
|||
setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
uint32_t tlsPtr = process->getSyscallArg(tc, 0);
|
||||
int index = 0;
|
||||
uint32_t tlsPtr = process->getSyscallArg(tc, index);
|
||||
|
||||
tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0,
|
||||
(uint8_t *)&tlsPtr, sizeof(tlsPtr));
|
||||
|
@ -511,12 +513,12 @@ ArmLinuxProcess::startup()
|
|||
}
|
||||
|
||||
ArmISA::IntReg
|
||||
ArmLinuxProcess::getSyscallArg(ThreadContext *tc, int i)
|
||||
ArmLinuxProcess::getSyscallArg(ThreadContext *tc, int &i)
|
||||
{
|
||||
// Linux apparently allows more parameter than the ABI says it should.
|
||||
// This limit may need to be increased even further.
|
||||
assert(i < 6);
|
||||
return tc->readIntReg(ArgumentReg0 + i);
|
||||
return tc->readIntReg(ArgumentReg0 + i++);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -44,7 +44,7 @@ class ArmLinuxProcess : public ArmLiveProcess
|
|||
|
||||
void startup();
|
||||
|
||||
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int i);
|
||||
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
|
||||
void setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val);
|
||||
|
||||
/// The target system's hostname.
|
||||
|
|
|
@ -55,23 +55,24 @@ namespace ArmISA
|
|||
|
||||
enum MiscRegIndex {
|
||||
MISCREG_CPSR = 0,
|
||||
MISCREG_SPSR,
|
||||
MISCREG_SPSR,
|
||||
MISCREG_SPSR_FIQ,
|
||||
MISCREG_SPSR_IRQ,
|
||||
MISCREG_SPSR_SVC,
|
||||
MISCREG_SPSR_MON,
|
||||
MISCREG_SPSR_UND,
|
||||
MISCREG_SPSR_ABT,
|
||||
MISCREG_FPSR,
|
||||
MISCREG_FPSID,
|
||||
MISCREG_FPSCR,
|
||||
MISCREG_FPEXC,
|
||||
NUM_MISCREGS
|
||||
MISCREG_SCTLR,
|
||||
NUM_MISCREGS
|
||||
};
|
||||
|
||||
const char * const miscRegName[NUM_MISCREGS] = {
|
||||
"cpsr",
|
||||
"spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und", "spsr_abt",
|
||||
"fpsr"
|
||||
"cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und",
|
||||
"spsr_abt", "fpsr", "fpsid", "fpscr", "fpexc", "sctlr"
|
||||
};
|
||||
|
||||
BitUnion32(CPSR)
|
||||
|
@ -80,8 +81,10 @@ namespace ArmISA
|
|||
Bitfield<29> c;
|
||||
Bitfield<28> v;
|
||||
Bitfield<27> q;
|
||||
Bitfield<26,25> it1;
|
||||
Bitfield<24> j;
|
||||
Bitfield<19, 16> ge;
|
||||
Bitfield<15,10> it2;
|
||||
Bitfield<9> e;
|
||||
Bitfield<8> a;
|
||||
Bitfield<7> i;
|
||||
|
@ -89,6 +92,35 @@ namespace ArmISA
|
|||
Bitfield<5> t;
|
||||
Bitfield<4, 0> mode;
|
||||
EndBitUnion(CPSR)
|
||||
|
||||
// This mask selects bits of the CPSR that actually go in the CondCodes
|
||||
// integer register to allow renaming.
|
||||
static const uint32_t CondCodesMask = 0xF80F0000;
|
||||
|
||||
BitUnion32(SCTLR)
|
||||
Bitfield<30> te; // Thumb Exception Enable
|
||||
Bitfield<29> afe; // Access flag enable
|
||||
Bitfield<28> tre; // TEX Remap bit
|
||||
Bitfield<27> nmfi;// Non-maskable fast interrupts enable
|
||||
Bitfield<25> ee; // Exception Endianness bit
|
||||
Bitfield<24> ve; // Interrupt vectors enable
|
||||
Bitfield<23> rao1;// Read as one
|
||||
Bitfield<22> u; // Alignment (now unused)
|
||||
Bitfield<21> fi; // Fast interrupts configuration enable
|
||||
Bitfield<18> rao2;// Read as one
|
||||
Bitfield<17> ha; // Hardware access flag enable
|
||||
Bitfield<16> rao3;// Read as one
|
||||
Bitfield<14> rr; // Round robin cache replacement
|
||||
Bitfield<13> v; // Base address for exception vectors
|
||||
Bitfield<12> i; // instruction cache enable
|
||||
Bitfield<11> z; // branch prediction enable bit
|
||||
Bitfield<10> sw; // Enable swp/swpb
|
||||
Bitfield<6,3> rao4;// Read as one
|
||||
Bitfield<7> b; // Endianness support (unused)
|
||||
Bitfield<2> c; // Cache enable bit
|
||||
Bitfield<1> a; // Alignment fault checking
|
||||
Bitfield<0> m; // MMU enable bit
|
||||
EndBitUnion(SCTLR)
|
||||
};
|
||||
|
||||
#endif // __ARCH_ARM_MISCREGS_HH__
|
||||
|
|
|
@ -97,7 +97,8 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
|
|||
changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]);
|
||||
|
||||
//CPSR
|
||||
newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR);
|
||||
newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR) |
|
||||
tc->readIntReg(INTREG_CONDCODES);
|
||||
changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]);
|
||||
}
|
||||
|
||||
|
|
|
@ -324,10 +324,10 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
|
|||
}
|
||||
|
||||
ArmISA::IntReg
|
||||
ArmLiveProcess::getSyscallArg(ThreadContext *tc, int i)
|
||||
ArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
|
||||
{
|
||||
assert(i < 4);
|
||||
return tc->readIntReg(ArgumentReg0 + i);
|
||||
return tc->readIntReg(ArgumentReg0 + i++);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -53,7 +53,7 @@ class ArmLiveProcess : public LiveProcess
|
|||
public:
|
||||
void argsInit(int intSize, int pageSize);
|
||||
|
||||
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int i);
|
||||
ArmISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
|
||||
void setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val);
|
||||
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
|
||||
};
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define __ARCH_ARM_REGISTERS_HH__
|
||||
|
||||
#include "arch/arm/max_inst_regs.hh"
|
||||
#include "arch/arm/intregs.hh"
|
||||
#include "arch/arm/miscregs.hh"
|
||||
|
||||
namespace ArmISA {
|
||||
|
@ -51,13 +52,11 @@ typedef float FloatReg;
|
|||
typedef uint64_t MiscReg;
|
||||
|
||||
// Constants Related to the number of registers
|
||||
const int NumIntArchRegs = 16;
|
||||
const int NumIntSpecialRegs = 19;
|
||||
const int NumIntArchRegs = NUM_ARCH_INTREGS;
|
||||
const int NumFloatArchRegs = 16;
|
||||
const int NumFloatSpecialRegs = 5;
|
||||
const int NumInternalProcRegs = 0;
|
||||
|
||||
const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs;
|
||||
const int NumIntRegs = NUM_INTREGS;
|
||||
const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;
|
||||
|
||||
const int NumMiscRegs = NUM_MISCREGS;
|
||||
|
@ -72,12 +71,11 @@ const int ArgumentReg1 = 1;
|
|||
const int ArgumentReg2 = 2;
|
||||
const int ArgumentReg3 = 3;
|
||||
const int FramePointerReg = 11;
|
||||
const int StackPointerReg = 13;
|
||||
const int ReturnAddressReg = 14;
|
||||
const int PCReg = 15;
|
||||
const int StackPointerReg = INTREG_SP;
|
||||
const int ReturnAddressReg = INTREG_LR;
|
||||
const int PCReg = INTREG_PC;
|
||||
|
||||
const int ZeroReg = NumIntArchRegs;
|
||||
const int AddrReg = ZeroReg + 1; // Used to generate address for uops
|
||||
const int ZeroReg = INTREG_ZERO;
|
||||
|
||||
const int SyscallNumReg = ReturnValueReg;
|
||||
const int SyscallPseudoReturnReg = ReturnValueReg;
|
||||
|
@ -116,35 +114,6 @@ enum FCSRFields {
|
|||
Cause_Field = 11
|
||||
};
|
||||
|
||||
enum MiscIntRegNums {
|
||||
zero_reg = NumIntArchRegs,
|
||||
addr_reg,
|
||||
|
||||
rhi,
|
||||
rlo,
|
||||
|
||||
r8_fiq, /* FIQ mode register bank */
|
||||
r9_fiq,
|
||||
r10_fiq,
|
||||
r11_fiq,
|
||||
r12_fiq,
|
||||
|
||||
r13_fiq, /* FIQ mode SP and LR */
|
||||
r14_fiq,
|
||||
|
||||
r13_irq, /* IRQ mode SP and LR */
|
||||
r14_irq,
|
||||
|
||||
r13_svc, /* SVC mode SP and LR */
|
||||
r14_svc,
|
||||
|
||||
r13_undef, /* UNDEF mode SP and LR */
|
||||
r14_undef,
|
||||
|
||||
r13_abt, /* ABT mode SP and LR */
|
||||
r14_abt
|
||||
};
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
#endif
|
||||
|
|
151
src/arch/arm/stacktrace.cc
Normal file
151
src/arch/arm/stacktrace.cc
Normal 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 ®, 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
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005 The Regents of The University of Michigan
|
||||
* Copyright (c) 2007-2008 The Florida State University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,8 +25,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
* Stephen Hines
|
||||
* Authors: Nathan Binkert
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_STACKTRACE_HH__
|
||||
|
@ -37,11 +35,11 @@
|
|||
#include "cpu/static_inst.hh"
|
||||
|
||||
class ThreadContext;
|
||||
class StackTrace;
|
||||
|
||||
namespace ArmISA
|
||||
{
|
||||
|
||||
class StackTrace;
|
||||
|
||||
class ProcessInfo
|
||||
{
|
||||
private:
|
||||
|
@ -64,7 +62,7 @@ class ProcessInfo
|
|||
class StackTrace
|
||||
{
|
||||
protected:
|
||||
typedef TheISA::MachInst MachInst;
|
||||
typedef ArmISA::MachInst MachInst;
|
||||
private:
|
||||
ThreadContext *tc;
|
||||
std::vector<Addr> stack;
|
||||
|
@ -94,10 +92,6 @@ class StackTrace
|
|||
public:
|
||||
const std::vector<Addr> &getstack() const { return stack; }
|
||||
|
||||
static const int user = 1;
|
||||
static const int console = 2;
|
||||
static const int unknown = 3;
|
||||
|
||||
#if TRACING_ON
|
||||
private:
|
||||
void dump();
|
||||
|
@ -123,6 +117,6 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
|||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // Namespace ArmISA
|
||||
|
||||
#endif // __ARCH_ARM_STACKTRACE_HH__
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2002-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,20 +24,28 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/*
|
||||
* TypeFieldAST.C
|
||||
*
|
||||
* Description: See TypeFieldAST.hh
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#include "arch/arm/system.hh"
|
||||
|
||||
#include "mem/slicc/ast/TypeFieldAST.hh"
|
||||
|
||||
TypeFieldAST::TypeFieldAST(PairListAST* pairs_ptr)
|
||||
: AST(pairs_ptr->getPairs()) {
|
||||
using namespace LittleEndianGuest;
|
||||
|
||||
ArmSystem::ArmSystem(Params *p)
|
||||
: System(p)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ArmSystem::~ArmSystem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ArmSystem *
|
||||
ArmSystemParams::create()
|
||||
{
|
||||
return new ArmSystem(this);
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,36 +24,33 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/*
|
||||
* StatementAST.C
|
||||
*
|
||||
* Description: See StatementAST.hh
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_ARM_SYSTEM_HH__
|
||||
#define __ARCH_ARM_SYSTEM_HH__
|
||||
|
||||
#include "mem/slicc/ast/StatementAST.hh"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static int indentation_depth = 1;
|
||||
#include "params/ArmSystem.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
void inc_indent()
|
||||
class ArmSystem : public System
|
||||
{
|
||||
indentation_depth++;
|
||||
}
|
||||
public:
|
||||
typedef ArmSystemParams Params;
|
||||
ArmSystem(Params *p);
|
||||
~ArmSystem();
|
||||
|
||||
void dec_indent()
|
||||
{
|
||||
indentation_depth--;
|
||||
}
|
||||
virtual Addr fixFuncEventAddr(Addr addr)
|
||||
{
|
||||
//XXX This may eventually have to do something useful.
|
||||
return addr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
string indent_str()
|
||||
{
|
||||
string temp;
|
||||
for(int i=0; i<indentation_depth; i++) {
|
||||
temp += " ";
|
||||
}
|
||||
return temp;
|
||||
}
|
|
@ -287,7 +287,15 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
|||
|
||||
return NoFault;
|
||||
#else
|
||||
fatal("translate atomic not yet implemented\n");
|
||||
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
|
||||
if (!sctlr.m) {
|
||||
req->setPaddr(req->getVaddr());
|
||||
return NoFault;
|
||||
}
|
||||
panic("MMU translation not implemented\n");
|
||||
return NoFault;
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -45,16 +45,20 @@ namespace ArmISA
|
|||
|
||||
// All the different types of opcode fields.
|
||||
Bitfield<27, 25> encoding;
|
||||
Bitfield<25> useImm;
|
||||
Bitfield<24, 21> opcode;
|
||||
Bitfield<24, 20> mediaOpcode;
|
||||
Bitfield<24> opcode24;
|
||||
Bitfield<23, 20> opcode23_20;
|
||||
Bitfield<23, 21> opcode23_21;
|
||||
Bitfield<20> opcode20;
|
||||
Bitfield<22> opcode22;
|
||||
Bitfield<19> opcode19;
|
||||
Bitfield<18> opcode18;
|
||||
Bitfield<15, 12> opcode15_12;
|
||||
Bitfield<15> opcode15;
|
||||
Bitfield<7, 4> miscOpcode;
|
||||
Bitfield<7,5> opc2;
|
||||
Bitfield<7> opcode7;
|
||||
Bitfield<4> opcode4;
|
||||
|
||||
|
@ -156,6 +160,7 @@ namespace ArmISA
|
|||
MODE_FIQ = 17,
|
||||
MODE_IRQ = 18,
|
||||
MODE_SVC = 19,
|
||||
MODE_MON = 22,
|
||||
MODE_ABORT = 23,
|
||||
MODE_UNDEFINED = 27,
|
||||
MODE_SYSTEM = 31
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,49 +24,53 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/*
|
||||
* ExprStatementAST.C
|
||||
*
|
||||
* Description: See ExprStatementAST.hh
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mem/slicc/ast/ExprStatementAST.hh"
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
|
||||
ExprStatementAST::ExprStatementAST(ExprAST* expr_ptr)
|
||||
: StatementAST()
|
||||
|
||||
namespace ArmISA {
|
||||
|
||||
void
|
||||
initCPU(ThreadContext *tc, int cpuId)
|
||||
{
|
||||
m_expr_ptr = expr_ptr;
|
||||
// Reset CP15?? What does that mean -- ali
|
||||
|
||||
// FPEXC.EN = 0
|
||||
|
||||
static Fault reset = new Reset;
|
||||
if (cpuId == 0)
|
||||
reset->invoke(tc);
|
||||
}
|
||||
|
||||
ExprStatementAST::~ExprStatementAST()
|
||||
{
|
||||
delete m_expr_ptr;
|
||||
uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
|
||||
#if FULL_SYSTEM
|
||||
panic("getArgument() not implemented for ARM!\n");
|
||||
#else
|
||||
panic("getArgument() only implemented for FULL_SYSTEM\n");
|
||||
M5_DUMMY_RETURN
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExprStatementAST::generate(string& code, Type* return_type_ptr) const
|
||||
Fault
|
||||
setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2)
|
||||
{
|
||||
code += indent_str();
|
||||
Type* actual_type_ptr = m_expr_ptr->generate(code);
|
||||
code += ";\n";
|
||||
|
||||
// The return type must be void
|
||||
Type* expected_type_ptr = g_sym_table.getType("void");
|
||||
if (expected_type_ptr != actual_type_ptr) {
|
||||
m_expr_ptr->error("Non-void return must not be ignored, return type is '" + actual_type_ptr->toString() + "'");
|
||||
}
|
||||
return new UnimpFault(csprintf("MCR CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n",
|
||||
CRn, opc1, CRm, opc2));
|
||||
}
|
||||
|
||||
void ExprStatementAST::findResources(Map<Var*, string>& resource_list) const
|
||||
Fault
|
||||
readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2)
|
||||
{
|
||||
m_expr_ptr->findResources(resource_list);
|
||||
return new UnimpFault(csprintf("MRC CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n",
|
||||
CRn, opc1, CRm, opc2));
|
||||
|
||||
}
|
||||
|
||||
void ExprStatementAST::print(ostream& out) const
|
||||
{
|
||||
out << "[ExprStatementAST: " << *m_expr_ptr << "]";
|
||||
|
||||
}
|
|
@ -125,6 +125,20 @@ namespace ArmISA {
|
|||
{
|
||||
panic("Copy Misc. Regs Not Implemented Yet\n");
|
||||
}
|
||||
|
||||
void initCPU(ThreadContext *tc, int cpuId);
|
||||
|
||||
static inline bool
|
||||
inUserMode(ThreadContext *tc)
|
||||
{
|
||||
return (tc->readMiscRegNoEffect(MISCREG_CPSR) & 0x1f) == MODE_USER;
|
||||
}
|
||||
|
||||
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
|
||||
|
||||
Fault setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
|
||||
Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -34,10 +34,6 @@ import traceback
|
|||
# get type names
|
||||
from types import *
|
||||
|
||||
# Prepend the directory where the PLY lex & yacc modules are found
|
||||
# to the search path.
|
||||
sys.path[0:0] = [os.environ['M5_PLY']]
|
||||
|
||||
from ply import lex
|
||||
from ply import yacc
|
||||
|
||||
|
|
|
@ -28,10 +28,11 @@
|
|||
#
|
||||
# Authors: Jaidev Patwardhan
|
||||
|
||||
from m5 import build_env
|
||||
from m5.defines import buildEnv
|
||||
|
||||
from System import *
|
||||
|
||||
if build_env['FULL_SYSTEM']:
|
||||
if buildEnv['FULL_SYSTEM']:
|
||||
class BareIronMipsSystem(MipsSystem):
|
||||
type = 'BareIronMipsSystem'
|
||||
system_type = 34
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
# Authors: Jaidev Patwardhan
|
||||
# Korey Sewell
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.defines import buildEnv
|
||||
from m5.params import *
|
||||
|
||||
from BaseCPU import BaseCPU
|
||||
|
||||
class BaseMipsCPU(BaseCPU)
|
||||
if build_env['TARGET_ISA'] == 'mips':
|
||||
if buildEnv['TARGET_ISA'] == 'mips':
|
||||
CP0_IntCtl_IPTI = Param.Unsigned(0,"No Description")
|
||||
CP0_IntCtl_IPPCI = Param.Unsigned(0,"No Description")
|
||||
CP0_SrsCtl_HSS = Param.Unsigned(0,"No Description")
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
#
|
||||
# Authors: Jaidev Patwardhan
|
||||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.defines import buildEnv
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from m5 import build_env
|
||||
|
||||
from System import System
|
||||
|
||||
class MipsSystem(System):
|
||||
|
@ -42,7 +42,7 @@ class MipsSystem(System):
|
|||
system_type = Param.UInt64("Type of system we are emulating")
|
||||
system_rev = Param.UInt64("Revision of system we are emulating")
|
||||
|
||||
if build_env['FULL_SYSTEM']:
|
||||
if buildEnv['FULL_SYSTEM']:
|
||||
class LinuxMipsSystem(MipsSystem):
|
||||
type = 'LinuxMipsSystem'
|
||||
system_type = 34
|
||||
|
|
|
@ -463,6 +463,8 @@ MipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl)
|
|||
uint64_t b_values[SIMD_MAX_VALS];
|
||||
uint64_t c_values[SIMD_MAX_VALS];
|
||||
|
||||
memset(c_values, 0, sizeof(c_values));
|
||||
|
||||
simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
|
||||
simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
|
||||
|
||||
|
@ -743,7 +745,7 @@ MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
|
|||
int nvals = SIMD_NVALS[fmt];
|
||||
uint64_t a_values[SIMD_MAX_VALS];
|
||||
uint64_t b_values[SIMD_MAX_VALS];
|
||||
int64_t temp[2];
|
||||
int64_t temp[2] = {0, 0};
|
||||
uint32_t ouflag = 0;
|
||||
|
||||
simdUnpack(a, a_values, fmt, SIGNED);
|
||||
|
|
|
@ -172,8 +172,11 @@ namespace MipsISA
|
|||
return reg;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
void serialize(EventManager *em, std::ostream &os)
|
||||
{}
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string §ion)
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -619,7 +619,7 @@ def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3;
|
|||
|
||||
def format Prefetch(ea_code = {{ EA = Rs + disp; }},
|
||||
mem_flags = [], pf_flags = [], inst_flags = []) {{
|
||||
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
|
||||
pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
|
||||
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
|
||||
'IsDataPrefetch', 'MemReadOp']
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ class MipsLinux : public Linux
|
|||
static const unsigned TIOCISATTY_ = 0x5480;
|
||||
static const unsigned TIOCGETS_ = 0x540d;
|
||||
static const unsigned TIOCGETA_ = 0x7417;
|
||||
static const unsigned TCSETAW_ = 0x5403; // 2.6.15 kernel
|
||||
//@}
|
||||
|
||||
/// For table().
|
||||
|
@ -126,6 +127,22 @@ class MipsLinux : public Linux
|
|||
/// assign themselves to process IDs reserved for
|
||||
/// the root users.
|
||||
static const int NUM_ROOT_PROCS = 2;
|
||||
|
||||
typedef struct {
|
||||
int32_t uptime; /* Seconds since boot */
|
||||
uint32_t loads[3]; /* 1, 5, and 15 minute load averages */
|
||||
uint32_t totalram; /* Total usable main memory size */
|
||||
uint32_t freeram; /* Available memory size */
|
||||
uint32_t sharedram; /* Amount of shared memory */
|
||||
uint32_t bufferram; /* Memory used by buffers */
|
||||
uint32_t totalswap; /* Total swap space size */
|
||||
uint32_t freeswap; /* swap space still available */
|
||||
uint16_t procs; /* Number of current processes */
|
||||
uint32_t totalhigh; /* Total high memory size */
|
||||
uint32_t freehigh; /* Available high memory size */
|
||||
uint32_t mem_unit; /* Memory unit size in bytes */
|
||||
} tgt_sysinfo;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,8 @@ static SyscallReturn
|
|||
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
|
||||
int index = 0;
|
||||
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
|
||||
|
||||
strcpy(name->sysname, "Linux");
|
||||
strcpy(name->nodename,"m5.eecs.umich.edu");
|
||||
|
@ -70,14 +71,16 @@ static SyscallReturn
|
|||
sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
unsigned op = process->getSyscallArg(tc, 0);
|
||||
// unsigned nbytes = process->getSyscallArg(tc, 2);
|
||||
int index = 0;
|
||||
unsigned op = process->getSyscallArg(tc, index);
|
||||
unsigned bufPtr = process->getSyscallArg(tc, index);
|
||||
// unsigned nbytes = process->getSyscallArg(tc, index);
|
||||
|
||||
switch (op) {
|
||||
case 45:
|
||||
{
|
||||
// GSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> fpcr(bufPtr);
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
*fpcr = 0;
|
||||
fpcr.copyOut(tc->getMemPort());
|
||||
|
@ -97,15 +100,17 @@ static SyscallReturn
|
|||
sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
unsigned op = process->getSyscallArg(tc, 0);
|
||||
// unsigned nbytes = process->getSyscallArg(tc, 2);
|
||||
int index = 0;
|
||||
unsigned op = process->getSyscallArg(tc, index);
|
||||
Addr bufPtr = process->getSyscallArg(tc, index);
|
||||
// unsigned nbytes = process->getSyscallArg(tc, index);
|
||||
|
||||
switch (op) {
|
||||
|
||||
case 14:
|
||||
{
|
||||
// SSI_IEEE_FP_CONTROL
|
||||
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
|
||||
TypedBufferArg<uint64_t> fpcr(bufPtr);
|
||||
// I don't think this exactly matches the HW FPCR
|
||||
fpcr.copyIn(tc->getMemPort());
|
||||
DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
|
||||
|
@ -238,7 +243,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 113 */ SyscallDesc("vm86", unimplementedFunc),
|
||||
/* 114 */ SyscallDesc("wait4", unimplementedFunc),
|
||||
/* 115 */ SyscallDesc("swapoff", unimplementedFunc),
|
||||
/* 116 */ SyscallDesc("sysinfo", unimplementedFunc),
|
||||
/* 116 */ SyscallDesc("sysinfo", sysinfoFunc<MipsLinux>),
|
||||
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
|
||||
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
|
||||
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
|
||||
|
@ -413,12 +418,6 @@ MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
|
|||
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
|
||||
{ }
|
||||
|
||||
void
|
||||
MipsLinuxProcess::startup()
|
||||
{
|
||||
MipsLiveProcess::argsInit(MachineBytes, VMPageSize);
|
||||
}
|
||||
|
||||
SyscallDesc*
|
||||
MipsLinuxProcess::getDesc(int callnum)
|
||||
{
|
||||
|
|
|
@ -43,8 +43,6 @@ class MipsLinuxProcess : public MipsLiveProcess
|
|||
/// Constructor.
|
||||
MipsLinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
|
||||
|
||||
void startup();
|
||||
|
||||
virtual SyscallDesc* getDesc(int callnum);
|
||||
|
||||
/// The target system's hostname.
|
||||
|
|
|
@ -32,9 +32,15 @@
|
|||
|
||||
#include "arch/mips/isa_traits.hh"
|
||||
#include "arch/mips/process.hh"
|
||||
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
|
||||
#include "mem/page_table.hh"
|
||||
|
||||
#include "sim/process.hh"
|
||||
#include "sim/process_impl.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
|
@ -62,14 +68,89 @@ MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params,
|
|||
void
|
||||
MipsLiveProcess::startup()
|
||||
{
|
||||
Process::startup();
|
||||
|
||||
argsInit(MachineBytes, VMPageSize);
|
||||
}
|
||||
|
||||
void
|
||||
MipsLiveProcess::argsInit(int intSize, int pageSize)
|
||||
{
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
// Calculate how much space we need for arg & env arrays.
|
||||
int argv_array_size = intSize * (argv.size() + 1);
|
||||
int envp_array_size = intSize * (envp.size() + 1);
|
||||
int arg_data_size = 0;
|
||||
for (vector<string>::size_type i = 0; i < argv.size(); ++i) {
|
||||
arg_data_size += argv[i].size() + 1;
|
||||
}
|
||||
int env_data_size = 0;
|
||||
for (vector<string>::size_type i = 0; i < envp.size(); ++i) {
|
||||
env_data_size += envp[i].size() + 1;
|
||||
}
|
||||
|
||||
int space_needed =
|
||||
argv_array_size + envp_array_size + arg_data_size + env_data_size;
|
||||
if (space_needed < 32*1024)
|
||||
space_needed = 32*1024;
|
||||
|
||||
// set bottom of stack
|
||||
stack_min = stack_base - space_needed;
|
||||
// align it
|
||||
stack_min = roundDown(stack_min, pageSize);
|
||||
stack_size = stack_base - stack_min;
|
||||
// map memory
|
||||
pTable->allocate(stack_min, roundUp(stack_size, pageSize));
|
||||
|
||||
// map out initial stack contents
|
||||
// ========
|
||||
// NOTE: Using uint32_t hardcodes MIPS32 and not MIPS64
|
||||
// even if MIPS64 was intended. This is because the
|
||||
// copyStringArray function templates on the parameters.
|
||||
// Elegant way to check intSize and vary between 32/64?
|
||||
// ========
|
||||
uint32_t argv_array_base = stack_min + intSize; // room for argc
|
||||
uint32_t envp_array_base = argv_array_base + argv_array_size;
|
||||
uint32_t arg_data_base = envp_array_base + envp_array_size;
|
||||
uint32_t env_data_base = arg_data_base + arg_data_size;
|
||||
|
||||
// write contents to stack
|
||||
uint32_t argc = argv.size();
|
||||
|
||||
if (intSize == 8)
|
||||
argc = htog((uint64_t)argc);
|
||||
else if (intSize == 4)
|
||||
argc = htog((uint32_t)argc);
|
||||
else
|
||||
panic("Unknown int size");
|
||||
|
||||
|
||||
initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize);
|
||||
|
||||
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
|
||||
setSyscallArg(tc, 0, argc);
|
||||
setSyscallArg(tc, 1, argv_array_base);
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
Addr prog_entry = objFile->entryPoint();
|
||||
tc->setPC(prog_entry);
|
||||
tc->setNextPC(prog_entry + sizeof(MachInst));
|
||||
tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
|
||||
}
|
||||
|
||||
|
||||
MipsISA::IntReg
|
||||
MipsLiveProcess::getSyscallArg(ThreadContext *tc, int i)
|
||||
MipsLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
|
||||
{
|
||||
assert(i < 6);
|
||||
return tc->readIntReg(FirstArgumentReg + i);
|
||||
return tc->readIntReg(FirstArgumentReg + i++);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -45,10 +45,12 @@ class MipsLiveProcess : public LiveProcess
|
|||
protected:
|
||||
MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
|
||||
|
||||
virtual void startup();
|
||||
void startup();
|
||||
|
||||
void argsInit(int intSize, int pageSize);
|
||||
|
||||
public:
|
||||
MipsISA::IntReg getSyscallArg(ThreadContext *tc, int i);
|
||||
MipsISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
|
||||
void setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val);
|
||||
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
|
||||
};
|
||||
|
|
37
src/arch/power/PowerTLB.py
Normal file
37
src/arch/power/PowerTLB.py
Normal 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
61
src/arch/power/SConscript
Normal 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
33
src/arch/power/SConsopts
Normal 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')
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,48 +25,63 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
* Timothy M. Jones
|
||||
*/
|
||||
|
||||
#include "mem/slicc/symbols/Symbol.hh"
|
||||
#ifndef __ARCH_POWER_FAULTS_HH__
|
||||
#define __ARCH_POWER_FAULTS_HH__
|
||||
|
||||
Symbol::Symbol(string id, const Location& location, const Map<string, string>& pairs)
|
||||
#include "sim/faults.hh"
|
||||
|
||||
namespace PowerISA
|
||||
{
|
||||
m_id = id;
|
||||
m_location = location;
|
||||
m_pairs = pairs;
|
||||
if (!existPair("short")) {
|
||||
addPair("short", m_id);
|
||||
}
|
||||
m_used = false;
|
||||
|
||||
class PowerFault : public FaultBase
|
||||
{
|
||||
protected:
|
||||
FaultName _name;
|
||||
|
||||
PowerFault(FaultName name)
|
||||
: _name(name)
|
||||
{
|
||||
}
|
||||
|
||||
FaultName
|
||||
name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class UnimplementedOpcodeFault : public PowerFault
|
||||
{
|
||||
public:
|
||||
UnimplementedOpcodeFault()
|
||||
: PowerFault("Unimplemented Opcode")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MachineCheckFault : public PowerFault
|
||||
{
|
||||
public:
|
||||
MachineCheckFault()
|
||||
: PowerFault("Machine Check")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline Fault
|
||||
genMachineCheckFault()
|
||||
{
|
||||
return new MachineCheckFault();
|
||||
}
|
||||
|
||||
Symbol::Symbol(string id, const Location& location)
|
||||
{
|
||||
m_id = id;
|
||||
m_location = location;
|
||||
if (!existPair("short")) {
|
||||
addPair("short", m_id);
|
||||
}
|
||||
m_used = false;
|
||||
}
|
||||
} // PowerISA namespace
|
||||
|
||||
const string& Symbol::lookupPair(const string& key) const
|
||||
{
|
||||
if (!existPair(key)) {
|
||||
error("Value for pair '" + key + "' missing.");
|
||||
}
|
||||
return m_pairs.lookup(key);
|
||||
}
|
||||
|
||||
void Symbol::addPair(const string& key, const string& value)
|
||||
{
|
||||
if (existPair(key)) {
|
||||
warning("Pair key '" + key + "' re-defined. new: '" + value + "' old: '" + lookupPair(key) + "'");
|
||||
}
|
||||
m_pairs.add(key, value);
|
||||
}
|
||||
#endif // __ARCH_POWER_FAULTS_HH__
|
169
src/arch/power/insts/branch.cc
Normal file
169
src/arch/power/insts/branch.cc
Normal 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();
|
||||
}
|
241
src/arch/power/insts/branch.hh
Normal file
241
src/arch/power/insts/branch.hh
Normal 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__
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,33 +24,36 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Timothy M. Jones
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* */
|
||||
#include "arch/power/insts/condition.hh"
|
||||
|
||||
#include "mem/slicc/symbols/Var.hh"
|
||||
#include "mem/slicc/symbols/StateMachine.hh"
|
||||
using namespace PowerISA;
|
||||
|
||||
Var::Var(string id, const Location& location,
|
||||
Type* type_ptr, string code,
|
||||
const Map<string, string>& pairs,
|
||||
StateMachine* machine_ptr) : Symbol(id, location, pairs)
|
||||
std::string
|
||||
CondLogicOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
if (machine_ptr == NULL) {
|
||||
m_c_id = id;
|
||||
} else {
|
||||
m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name
|
||||
}
|
||||
std::stringstream ss;
|
||||
|
||||
m_machine_ptr = machine_ptr;
|
||||
m_type_ptr = type_ptr;
|
||||
m_code = code;
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
// Format is <mnemonic> bt, ba, bb
|
||||
ss << bt << ", " << ba << ", " << bb;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void Var::print(ostream& out) const
|
||||
std::string
|
||||
CondMoveOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
out << "[Var id: " << m_c_id << "]" << endl;
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
// Format is <mnemonic> bf, bfa
|
||||
ss << bf << ", " << bfa;
|
||||
|
||||
return ss.str();
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,61 +24,63 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Timothy M. Jones
|
||||
*/
|
||||
|
||||
/*
|
||||
* DeclAST.hh
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
#ifndef __ARCH_POWER_INSTS_CONDITION_HH__
|
||||
#define __ARCH_POWER_INSTS_CONDITION_HH__
|
||||
|
||||
#include "arch/power/insts/static_inst.hh"
|
||||
#include "base/cprintf.hh"
|
||||
|
||||
namespace PowerISA
|
||||
{
|
||||
|
||||
/**
|
||||
* Class for condition register logical operations.
|
||||
*/
|
||||
class CondLogicOp : public PowerStaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
#ifndef DECLAST_H
|
||||
#define DECLAST_H
|
||||
uint32_t ba;
|
||||
uint32_t bb;
|
||||
uint32_t bt;
|
||||
|
||||
#include "mem/slicc/slicc_global.hh"
|
||||
#include "mem/slicc/ast/AST.hh"
|
||||
#include "mem/slicc/ast/PairListAST.hh"
|
||||
#include "mem/slicc/symbols/StateMachine.hh"
|
||||
#include "mem/slicc/ast/TypeAST.hh"
|
||||
/// Constructor
|
||||
CondLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: PowerStaticInst(mnem, _machInst, __opClass),
|
||||
ba(machInst.ba),
|
||||
bb(machInst.bb),
|
||||
bt(machInst.bt)
|
||||
{
|
||||
}
|
||||
|
||||
class DeclAST : public AST {
|
||||
public:
|
||||
// Constructors
|
||||
DeclAST(PairListAST* pairs_ptr) : AST(pairs_ptr->getPairs()) {}
|
||||
|
||||
// Destructor
|
||||
virtual ~DeclAST() {}
|
||||
|
||||
// Public Methods
|
||||
virtual void generate() = 0;
|
||||
virtual void findMachines() {};
|
||||
|
||||
// void print(ostream& out) const;
|
||||
private:
|
||||
// Private Methods
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
// DeclAST(const DeclAST& obj);
|
||||
// DeclAST& operator=(const DeclAST& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const DeclAST& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const DeclAST& obj)
|
||||
/**
|
||||
* Class for condition register move operations.
|
||||
*/
|
||||
class CondMoveOp : public PowerStaticInst
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
protected:
|
||||
|
||||
#endif //DECLAST_H
|
||||
uint32_t bf;
|
||||
uint32_t bfa;
|
||||
|
||||
/// Constructor
|
||||
CondMoveOp(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: PowerStaticInst(mnem, _machInst, __opClass),
|
||||
bf(machInst.bf),
|
||||
bfa(machInst.bfa)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
} // PowerISA namespace
|
||||
|
||||
#endif //__ARCH_POWER_INSTS_CONDITION_HH__
|
60
src/arch/power/insts/floating.cc
Normal file
60
src/arch/power/insts/floating.cc
Normal 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();
|
||||
}
|
153
src/arch/power/insts/floating.hh
Normal file
153
src/arch/power/insts/floating.hh
Normal 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__
|
170
src/arch/power/insts/integer.cc
Normal file
170
src/arch/power/insts/integer.cc
Normal 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();
|
||||
}
|
176
src/arch/power/insts/integer.hh
Normal file
176
src/arch/power/insts/integer.hh
Normal 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__
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,62 +24,51 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Timothy M. Jones
|
||||
*/
|
||||
|
||||
/*
|
||||
* DeclListAST.C
|
||||
*
|
||||
* Description: See DeclListAST.hh
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#include "arch/power/insts/mem.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
|
||||
#include "mem/slicc/ast/DeclListAST.hh"
|
||||
using namespace PowerISA;
|
||||
|
||||
DeclListAST::DeclListAST(Vector<DeclAST*>* vec_ptr)
|
||||
: AST()
|
||||
std::string
|
||||
MemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
assert(vec_ptr != NULL);
|
||||
m_vec_ptr = vec_ptr;
|
||||
return csprintf("%-10s", mnemonic);
|
||||
}
|
||||
|
||||
// Singleton constructor.
|
||||
DeclListAST::DeclListAST(DeclAST* Decl_ptr)
|
||||
: AST()
|
||||
std::string
|
||||
MemDispOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
assert(Decl_ptr != NULL);
|
||||
m_vec_ptr = new Vector<DeclAST*>;
|
||||
m_vec_ptr->insertAtTop(Decl_ptr);
|
||||
}
|
||||
std::stringstream ss;
|
||||
|
||||
DeclListAST::~DeclListAST()
|
||||
{
|
||||
int size = m_vec_ptr->size();
|
||||
for(int i=0; i<size; i++) {
|
||||
delete (*m_vec_ptr)[i];
|
||||
}
|
||||
delete m_vec_ptr;
|
||||
}
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
void DeclListAST::generate() const
|
||||
{
|
||||
int size = m_vec_ptr->size();
|
||||
for(int i=0; i<size; i++) {
|
||||
(*m_vec_ptr)[i]->generate();
|
||||
}
|
||||
}
|
||||
// Print the destination only for a load
|
||||
if (!flags[IsStore]) {
|
||||
if (_numDestRegs > 0) {
|
||||
|
||||
void DeclListAST::findMachines() const
|
||||
{
|
||||
int size = m_vec_ptr->size();
|
||||
for(int i=0; i<size; i++) {
|
||||
(*m_vec_ptr)[i]->findMachines();
|
||||
}
|
||||
}
|
||||
// If the instruction updates the source register with the
|
||||
// EA, then this source register is placed in position 0,
|
||||
// therefore we print the last destination register.
|
||||
printReg(ss, _destRegIdx[_numDestRegs-1]);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclListAST::print(ostream& out) const
|
||||
{
|
||||
assert(m_vec_ptr != NULL);
|
||||
out << "[DeclListAST: " << *m_vec_ptr << "]";
|
||||
// Print the data register for a store
|
||||
else {
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
}
|
||||
|
||||
// Print the displacement
|
||||
ss << ", " << (int32_t)disp;
|
||||
|
||||
// Print the address register
|
||||
ss << "(";
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
ss << ")";
|
||||
|
||||
return ss.str();
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,62 +24,68 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Timothy M. Jones
|
||||
*/
|
||||
|
||||
/*
|
||||
* TypeDeclAST.C
|
||||
*
|
||||
* Description: See TypeDeclAST.hh
|
||||
*
|
||||
* $Id: TypeDeclAST.C,v 3.1 2003/03/22 15:15:17 xu Exp $
|
||||
*
|
||||
#ifndef __ARCH_POWER_MEM_HH__
|
||||
#define __ARCH_POWER_MEM_HH__
|
||||
|
||||
#include "arch/power/insts/static_inst.hh"
|
||||
|
||||
namespace PowerISA
|
||||
{
|
||||
|
||||
/**
|
||||
* Base class for memory operations.
|
||||
*/
|
||||
|
||||
#include "mem/slicc/ast/TypeDeclAST.hh"
|
||||
#include "mem/slicc/main.hh"
|
||||
#include "mem/slicc/symbols/SymbolTable.hh"
|
||||
|
||||
TypeDeclAST::TypeDeclAST(TypeAST* type_ast_ptr,
|
||||
PairListAST* pairs_ptr,
|
||||
Vector<TypeFieldAST*>* field_vec_ptr)
|
||||
: DeclAST(pairs_ptr)
|
||||
class MemOp : public PowerStaticInst
|
||||
{
|
||||
m_type_ast_ptr = type_ast_ptr;
|
||||
m_field_vec_ptr = field_vec_ptr;
|
||||
}
|
||||
protected:
|
||||
|
||||
TypeDeclAST::~TypeDeclAST()
|
||||
{
|
||||
delete m_type_ast_ptr;
|
||||
if (m_field_vec_ptr != NULL) {
|
||||
int size = m_field_vec_ptr->size();
|
||||
for(int i=0; i<size; i++) {
|
||||
delete (*m_field_vec_ptr)[i];
|
||||
/// Memory request flags. See mem_req_base.hh.
|
||||
unsigned memAccessFlags;
|
||||
/// Pointer to EAComp object.
|
||||
const StaticInstPtr eaCompPtr;
|
||||
/// Pointer to MemAcc object.
|
||||
const StaticInstPtr memAccPtr;
|
||||
|
||||
/// Constructor
|
||||
MemOp(const char *mnem, MachInst _machInst, OpClass __opClass,
|
||||
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
|
||||
StaticInstPtr _memAccPtr = nullStaticInstPtr)
|
||||
: PowerStaticInst(mnem, _machInst, __opClass),
|
||||
memAccessFlags(0),
|
||||
eaCompPtr(_eaCompPtr),
|
||||
memAccPtr(_memAccPtr)
|
||||
{
|
||||
}
|
||||
delete m_field_vec_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDeclAST::generate()
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class for memory operations with displacement.
|
||||
*/
|
||||
class MemDispOp : public MemOp
|
||||
{
|
||||
string machine_name;
|
||||
string id = m_type_ast_ptr->toString();
|
||||
protected:
|
||||
|
||||
// Make the new type
|
||||
Type* new_type_ptr = new Type(id, getLocation(), getPairs(),
|
||||
g_sym_table.getStateMachine());
|
||||
g_sym_table.newSym(new_type_ptr);
|
||||
int16_t disp;
|
||||
|
||||
// Add all of the fields of the type to it
|
||||
if (m_field_vec_ptr != NULL) {
|
||||
int size = m_field_vec_ptr->size();
|
||||
for(int i=0; i<size; i++) {
|
||||
(*m_field_vec_ptr)[i]->generate(new_type_ptr);
|
||||
/// Constructor
|
||||
MemDispOp(const char *mnem, MachInst _machInst, OpClass __opClass,
|
||||
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
|
||||
StaticInstPtr _memAccPtr = nullStaticInstPtr)
|
||||
: MemOp(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
|
||||
disp(machInst.d)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDeclAST::print(ostream& out) const
|
||||
{
|
||||
out << "[TypeDecl: " << m_type_ast_ptr->toString() << "]";
|
||||
}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
} // PowerISA namespace
|
||||
|
||||
#endif //__ARCH_POWER_INSTS_MEM_HH__
|
60
src/arch/power/insts/misc.cc
Normal file
60
src/arch/power/insts/misc.cc
Normal 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();
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,31 +24,34 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Timothy M. Jones
|
||||
*/
|
||||
|
||||
/*
|
||||
* LiteralExprAST.C
|
||||
*
|
||||
* Description: See LiteralExprAST.hh
|
||||
*
|
||||
* $Id: LiteralExprAST.C,v 3.1 2002/10/22 21:27:52 milo Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_POWER_INSTS_MISC_HH__
|
||||
#define __ARCH_POWER_INSTS_MISC_HH__
|
||||
|
||||
#include "mem/slicc/ast/LiteralExprAST.hh"
|
||||
#include "arch/power/insts/static_inst.hh"
|
||||
|
||||
Type* LiteralExprAST::generate(string& code) const
|
||||
namespace PowerISA
|
||||
{
|
||||
if (m_type == "string") {
|
||||
code += "(\"" + *m_lit_ptr + "\")";
|
||||
} else {
|
||||
code += "(" + *m_lit_ptr + ")";
|
||||
}
|
||||
|
||||
Type* type_ptr = g_sym_table.getType(m_type);
|
||||
if (type_ptr == NULL) {
|
||||
// Can't find the type
|
||||
error("Internal: can't primitive type '" + m_type + "'");
|
||||
}
|
||||
return type_ptr;
|
||||
}
|
||||
/**
|
||||
* Class for misc operations.
|
||||
*/
|
||||
class MiscOp : public PowerStaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
MiscOp(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: PowerStaticInst(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
} // PowerISA namespace
|
||||
|
||||
#endif //__ARCH_POWER_INSTS_MISC_HH__
|
62
src/arch/power/insts/static_inst.cc
Normal file
62
src/arch/power/insts/static_inst.cc
Normal 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();
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 The University of Edinburgh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,58 +24,47 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Timothy M. Jones
|
||||
*/
|
||||
|
||||
/*
|
||||
* PairListAST.hh
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_POWER_INSTS_STATICINST_HH__
|
||||
#define __ARCH_POWER_INSTS_STATICINST_HH__
|
||||
|
||||
#ifndef PairListAST_H
|
||||
#define PairListAST_H
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/static_inst.hh"
|
||||
|
||||
#include "mem/slicc/slicc_global.hh"
|
||||
#include "mem/slicc/ast/AST.hh"
|
||||
#include "mem/slicc/ast/PairAST.hh"
|
||||
namespace PowerISA
|
||||
{
|
||||
|
||||
class PowerStaticInst : public StaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
class PairListAST : public AST {
|
||||
public:
|
||||
// Constructors
|
||||
PairListAST() : AST() {}
|
||||
// Constructor
|
||||
PowerStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: StaticInst(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
//~PairListAST();
|
||||
// Insert a condition value into a CR (condition register) field
|
||||
inline uint32_t
|
||||
insertCRField(uint32_t cr, uint32_t bf, uint32_t value) const
|
||||
{
|
||||
uint32_t bits = value << ((7 - bf) * 4);
|
||||
uint32_t mask = ~(0xf << ((7 - bf) * 4));
|
||||
return (cr & mask) | bits;
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
void addPair(PairAST* pair_ptr);
|
||||
void print(ostream& out) const;
|
||||
private:
|
||||
// Private Methods
|
||||
/// Print a register name for disassembly given the unique
|
||||
/// dependence tag number (FP or int).
|
||||
void
|
||||
printReg(std::ostream &os, int reg) const;
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
PairListAST(const PairListAST& obj);
|
||||
PairListAST& operator=(const PairListAST& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
std::string
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const PairListAST& obj);
|
||||
} // PowerISA namespace
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const PairListAST& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //PairListAST_H
|
||||
#endif //__ARCH_POWER_INSTS_STATICINST_HH__
|
115
src/arch/power/isa.hh
Normal file
115
src/arch/power/isa.hh
Normal 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 §ion)
|
||||
{
|
||||
}
|
||||
|
||||
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
Loading…
Reference in a new issue