diff options
132 files changed, 5639 insertions, 4257 deletions
diff --git a/SConscript b/SConscript index fc2e6ae0b..3e607caa4 100644 --- a/SConscript +++ b/SConscript @@ -209,6 +209,7 @@ base_sources = Split(''' sim/configfile.cc sim/debug.cc sim/eventq.cc + sim/faults.cc sim/main.cc sim/param.cc sim/profile.cc @@ -222,14 +223,6 @@ base_sources = Split(''' sim/stat_control.cc sim/trace_context.cc ''') -# These are now included by the architecture specific SConscript -# arch/alpha/decoder.cc -# arch/alpha/alpha_o3_exec.cc -# arch/alpha/fast_cpu_exec.cc -# arch/alpha/simple_cpu_exec.cc -# arch/alpha/full_cpu_exec.cc -# arch/alpha/faults.cc -# arch/alpha/isa_traits.cc # MySql sources mysql_sources = Split(''' @@ -295,15 +288,6 @@ full_system_sources = Split(''' sim/pseudo_inst.cc ''') -# These are now included by the architecture specific SConscript -# arch/alpha/alpha_memory.cc -# arch/alpha/arguments.cc -# arch/alpha/ev5.cc -# arch/alpha/osfpal.cc -# arch/alpha/pseudo_inst.cc -# arch/alpha/stacktrace.cc -# arch/alpha/vtophys.cc - # turbolaser encumbered sources turbolaser_sources = Split(''' encumbered/dev/dma.cc @@ -330,14 +314,16 @@ syscall_emulation_sources = Split(''' encumbered/eio/eio.cc encumbered/eio/exolex.cc encumbered/eio/libexo.cc + kern/linux/linux.cc + kern/tru64/tru64.cc sim/process.cc sim/syscall_emul.cc ''') -# These are now included by the architecture specific SConscript -# arch/alpha/alpha_common_syscall_emul.cc -# arch/alpha/alpha_linux_process.cc -# arch/alpha/alpha_tru64_process.cc +# The following stuff (targetarch code and global define of THE_ISA) +# are legacy things that assume we're only compiling one ISA at a +# time. These will have to go away if we want to build a binary that +# supports multiple ISAs. targetarch_files = Split(''' alpha_linux_process.hh @@ -351,29 +337,20 @@ targetarch_files = Split(''' stacktrace.hh vtophys.hh ''') -# pseudo_inst.hh -# isa_traits.hh -# osfpal.hh -# byte_swap.hh -# alpha_common_syscall_emul.hh -# vptr.hh -# isa_fullsys_traits.hh # Set up bridging headers to the architecture specific versions for f in targetarch_files: env.Command('targetarch/' + f, 'arch/%s/%s' % (env['TARGET_ISA'], f), '''echo '#include "arch/%s/%s"' > $TARGET''' % (env['TARGET_ISA'], f)) -# Let the target architecture define what sources it needs -arch_source = SConscript('arch/%s/SConscript' % env['TARGET_ISA'], - build_dir = 'build/%s/' % env['BUILD_DIR'], - exports = 'env', duplicate = False) - # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) +arch_sources = SConscript('arch/SConscript', + exports = 'env', duplicate = False) + # Set up complete list of sources based on configuration. -sources = base_sources + arch_source +sources = base_sources + arch_sources if env['FULL_SYSTEM']: sources += full_system_sources @@ -390,27 +367,6 @@ for opt in env.ExportOptions: ################################################### # -# Add an SCons scanner for ISA files -# -################################################### -import SCons.Scanner - -def ISAScan(): - return SCons.Scanner.Classic("ISAScan", - "$ISASUFFIXES", - "SRCDIR", - '^[ \t]*##[ \t]*include[ \t]*"([^>"]+)"') - -def ISAPath(env, dir, target=None, source=None, a=None): - return (Dir(env['SRCDIR']), Dir('.')) - -iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"], - path_function = ISAPath) -env.Append(SCANNERS = iscan) - - -################################################### -# # Special build rules. # ################################################### @@ -421,27 +377,6 @@ env.Command(Split('base/traceflags.hh base/traceflags.cc'), 'base/traceflags.py', 'python $SOURCE $TARGET.base') -# several files are generated from arch/$TARGET_ISA/isa_desc. -env.Command(Split(''' - arch/%s/decoder.cc - arch/%s/decoder.hh - arch/%s/alpha_o3_exec.cc - arch/%s/fast_cpu_exec.cc - arch/%s/simple_cpu_exec.cc - arch/%s/full_cpu_exec.cc''' % - (env['TARGET_ISA'], - env['TARGET_ISA'], - env['TARGET_ISA'], - env['TARGET_ISA'], - env['TARGET_ISA'], - env['TARGET_ISA'])), - Split(''' - arch/%s/isa/main.isa - arch/isa_parser.py''' % - env['TARGET_ISA']), - '$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/%s' % env['TARGET_ISA']) - - # libelf build is described in its own SConscript file. # SConscript-local is the per-config build, which just copies some # header files into a place where they can be found. diff --git a/arch/SConscript b/arch/SConscript new file mode 100644 index 000000000..51f6cc023 --- /dev/null +++ b/arch/SConscript @@ -0,0 +1,146 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os.path + +# Import build environment variable from SConstruct. +Import('env') + +# Right now there are no source files immediately in this directory +sources = [] + +################################################################# +# +# ISA "switch header" generation. +# +# Auto-generate arch headers that include the right ISA-specific +# header based on the setting of THE_ISA preprocessor variable. +# +################################################################# + +# List of headers to generate +isa_switch_hdrs = Split(''' + isa_traits.hh + ''') + +# Generate the header. target[0] is the full path of the output +# header to generate. 'source' is a dummy variable, since we get the +# list of ISAs from env['ALL_ISA_LIST']. +def gen_switch_hdr(target, source, env): + fname = str(target[0]) + basename = os.path.basename(fname) + f = open(fname, 'w') + f.write('#include "arch/isa_specific.hh"\n') + cond = '#if' + for isa in env['ALL_ISA_LIST']: + f.write('%s THE_ISA == %s_ISA\n#include "arch/%s/%s"\n' + % (cond, isa.upper(), isa, basename)) + cond = '#elif' + f.write('#else\n#error "THE_ISA not set"\n#endif\n') + f.close() + return 0 + +# String to print when generating header +def gen_switch_hdr_string(target, source, env): + return "Generating ISA switch header " + str(target[0]) + +# Build SCons Action object. 'varlist' specifies env vars that this +# action depdnds on; when env['ALL_ISA_LIST'] changes these actions +# should get re-executed. +switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string, + varlist=['ALL_ISA_LIST']) + +# Instantiate actions for each header +for hdr in isa_switch_hdrs: + env.Command(hdr, [], switch_hdr_action) + +################################################################# +# +# Include architecture-specific files. +# +################################################################# + +# +# Build a SCons scanner for ISA files +# +import SCons.Scanner + +def ISAScan(): + return SCons.Scanner.Classic("ISAScan", + "$ISASUFFIXES", + "SRCDIR", + '^[ \t]*##[ \t]*include[ \t]*"([^>"]+)"') + +def ISAPath(env, dir, target=None, source=None, a=None): + return (Dir(env['SRCDIR']), Dir('.')) + +iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"], + path_function = ISAPath) +env.Append(SCANNERS = iscan) + +# +# Now create a Builder object that uses isa_parser.py to generate C++ +# output from the ISA description (*.isa) files. +# + +# several files are generated from the ISA description +isa_desc_gen_files = Split(''' + decoder.cc + alpha_o3_exec.cc + fast_cpu_exec.cc + simple_cpu_exec.cc + full_cpu_exec.cc + decoder.hh + ''') + +# Convert to File node to fix path +isa_parser = File('isa_parser.py') + +# The emitter patches up the sources & targets to include the +# autogenerated files as targets and isa parser itself as a source. +def isa_desc_emitter(target, source, env): + return (isa_desc_gen_files, [isa_parser] + source) + +# Pieces are in place, so create the builder. +isa_desc_builder = Builder(action='${SOURCES[0]} ${SOURCES[1]} $TARGET.dir', + source_scanner = iscan, + emitter = isa_desc_emitter) + +env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) + +# +# Now include other ISA-specific sources from the ISA subdirectories. +# + +isa = env['TARGET_ISA'] # someday this may be a list of ISAs + +# Let the target architecture define what additional sources it needs +sources += SConscript(os.path.join(isa, 'SConscript'), + exports = 'env', duplicate = False) + +Return('sources') diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript index 8bf408c06..050dfb9cf 100644 --- a/arch/alpha/SConscript +++ b/arch/alpha/SConscript @@ -43,445 +43,45 @@ Import('env') ################################################### # Base sources used by all configurations. -arch_base_sources = Split(''' - arch/alpha/decoder.cc - arch/alpha/alpha_o3_exec.cc - arch/alpha/fast_cpu_exec.cc - arch/alpha/simple_cpu_exec.cc - arch/alpha/full_cpu_exec.cc - arch/alpha/faults.cc - arch/alpha/isa_traits.cc +base_sources = Split(''' + faults.cc + isa_traits.cc ''') -# base/circlebuf.cc -# base/copyright.cc -# base/cprintf.cc -# base/embedfile.cc -# base/fast_alloc.cc -# base/fifo_buffer.cc -# base/hostinfo.cc -# base/hybrid_pred.cc -# base/inifile.cc -# base/intmath.cc -# base/match.cc -# base/misc.cc -# base/output.cc -# base/pollevent.cc -# base/range.cc -# base/random.cc -# base/sat_counter.cc -# base/socket.cc -# base/statistics.cc -# base/str.cc -# base/time.cc -# base/trace.cc -# base/traceflags.cc -# base/userinfo.cc -# base/compression/lzss_compression.cc -# base/loader/aout_object.cc -# base/loader/ecoff_object.cc -# base/loader/elf_object.cc -# base/loader/object_file.cc -# base/loader/symtab.cc -# base/stats/events.cc -# base/stats/statdb.cc -# base/stats/visit.cc -# base/stats/text.cc -# -# cpu/base.cc -# cpu/base_dyn_inst.cc -# cpu/exec_context.cc -# cpu/exetrace.cc -# cpu/pc_event.cc -# cpu/static_inst.cc -# cpu/o3/2bit_local_pred.cc -# cpu/o3/alpha_dyn_inst.cc -# cpu/o3/alpha_cpu.cc -# cpu/o3/alpha_cpu_builder.cc -# cpu/o3/bpred_unit.cc -# cpu/o3/btb.cc -# cpu/o3/commit.cc -# cpu/o3/decode.cc -# cpu/o3/fetch.cc -# cpu/o3/free_list.cc -# cpu/o3/cpu.cc -# cpu/o3/iew.cc -# cpu/o3/inst_queue.cc -# cpu/o3/ldstq.cc -# cpu/o3/mem_dep_unit.cc -# cpu/o3/ras.cc -# cpu/o3/rename.cc -# cpu/o3/rename_map.cc -# cpu/o3/rob.cc -# cpu/o3/sat_counter.cc -# cpu/o3/store_set.cc -# cpu/o3/tournament_pred.cc -# cpu/fast/cpu.cc -# cpu/sampler/sampler.cc -# cpu/simple/cpu.cc -# cpu/trace/reader/mem_trace_reader.cc -# cpu/trace/reader/ibm_reader.cc -# cpu/trace/reader/itx_reader.cc -# cpu/trace/reader/m5_reader.cc -# cpu/trace/opt_cpu.cc -# cpu/trace/trace_cpu.cc -# -# encumbered/cpu/full/bpred.cc -# encumbered/cpu/full/commit.cc -# encumbered/cpu/full/cpu.cc -# encumbered/cpu/full/create_vector.cc -# encumbered/cpu/full/cv_spec_state.cc -# encumbered/cpu/full/dd_queue.cc -# encumbered/cpu/full/dep_link.cc -# encumbered/cpu/full/dispatch.cc -# encumbered/cpu/full/dyn_inst.cc -# encumbered/cpu/full/execute.cc -# encumbered/cpu/full/fetch.cc -# encumbered/cpu/full/floss_reasons.cc -# encumbered/cpu/full/fu_pool.cc -# encumbered/cpu/full/inst_fifo.cc -# encumbered/cpu/full/instpipe.cc -# encumbered/cpu/full/issue.cc -# encumbered/cpu/full/ls_queue.cc -# encumbered/cpu/full/machine_queue.cc -# encumbered/cpu/full/pipetrace.cc -# encumbered/cpu/full/readyq.cc -# encumbered/cpu/full/reg_info.cc -# encumbered/cpu/full/rob_station.cc -# encumbered/cpu/full/spec_memory.cc -# encumbered/cpu/full/spec_state.cc -# encumbered/cpu/full/storebuffer.cc -# encumbered/cpu/full/writeback.cc -# encumbered/cpu/full/iq/iq_station.cc -# encumbered/cpu/full/iq/iqueue.cc -# encumbered/cpu/full/iq/segmented/chain_info.cc -# encumbered/cpu/full/iq/segmented/chain_wire.cc -# encumbered/cpu/full/iq/segmented/iq_seg.cc -# encumbered/cpu/full/iq/segmented/iq_segmented.cc -# encumbered/cpu/full/iq/segmented/seg_chain.cc -# encumbered/cpu/full/iq/seznec/iq_seznec.cc -# encumbered/cpu/full/iq/standard/iq_standard.cc -# encumbered/mem/functional/main.cc -# -# mem/base_hier.cc -# mem/base_mem.cc -# mem/hier_params.cc -# mem/mem_cmd.cc -# mem/mem_debug.cc -# mem/mem_req.cc -# mem/memory_interface.cc -# mem/bus/base_interface.cc -# mem/bus/bus.cc -# mem/bus/bus_bridge.cc -# mem/bus/bus_bridge_master.cc -# mem/bus/bus_bridge_slave.cc -# mem/bus/bus_interface.cc -# mem/bus/dma_bus_interface.cc -# mem/bus/dma_interface.cc -# mem/bus/master_interface.cc -# mem/bus/slave_interface.cc -# mem/cache/base_cache.cc -# mem/cache/cache.cc -# mem/cache/cache_builder.cc -# mem/cache/coherence/coherence_protocol.cc -# mem/cache/coherence/uni_coherence.cc -# mem/cache/miss/blocking_buffer.cc -# mem/cache/miss/miss_queue.cc -# mem/cache/miss/mshr.cc -# mem/cache/miss/mshr_queue.cc -# mem/cache/prefetch/base_prefetcher.cc -# mem/cache/prefetch/prefetcher.cc -# mem/cache/prefetch/tagged_prefetcher.cc -# mem/cache/tags/base_tags.cc -# mem/cache/tags/cache_tags.cc -# mem/cache/tags/fa_lru.cc -# mem/cache/tags/iic.cc -# mem/cache/tags/lru.cc -# mem/cache/tags/repl/gen.cc -# mem/cache/tags/repl/repl.cc -# mem/cache/tags/split.cc -# mem/cache/tags/split_lru.cc -# mem/cache/tags/split_lifo.cc -# mem/functional/functional.cc -# mem/timing/base_memory.cc -# mem/timing/memory_builder.cc -# mem/timing/simple_mem_bank.cc -# mem/trace/itx_writer.cc -# mem/trace/mem_trace_writer.cc -# mem/trace/m5_writer.cc -# -# python/pyconfig.cc -# python/embedded_py.cc -# -# sim/builder.cc -# sim/configfile.cc -# sim/debug.cc -# sim/eventq.cc -# sim/main.cc -# sim/param.cc -# sim/profile.cc -# sim/root.cc -# sim/serialize.cc -# sim/sim_events.cc -# sim/sim_exit.cc -# sim/sim_object.cc -# sim/startup.cc -# sim/stat_context.cc -# sim/stat_control.cc -# sim/trace_context.cc -# ''') - -# MySql sources -arch_mysql_sources = Split(''' - ''') -# base/mysql.cc -# base/stats/mysql.cc -# ''') - # Full-system sources -arch_full_system_sources = Split(''' - arch/alpha/alpha_memory.cc - arch/alpha/arguments.cc - arch/alpha/ev5.cc - arch/alpha/osfpal.cc - arch/alpha/stacktrace.cc - arch/alpha/vtophys.cc +full_system_sources = Split(''' + alpha_memory.cc + arguments.cc + ev5.cc + osfpal.cc + stacktrace.cc + vtophys.cc ''') -# base/crc.cc -# base/inet.cc -# base/remote_gdb.cc -# -# cpu/intr_control.cc -# cpu/profile.cc -# -# dev/alpha_console.cc -# dev/baddev.cc -# dev/simconsole.cc -# dev/disk_image.cc -# dev/etherbus.cc -# dev/etherdump.cc -# dev/etherint.cc -# dev/etherlink.cc -# dev/etherpkt.cc -# dev/ethertap.cc -# dev/ide_ctrl.cc -# dev/ide_disk.cc -# dev/io_device.cc -# dev/ns_gige.cc -# dev/pciconfigall.cc -# dev/pcidev.cc -# dev/pcifake.cc -# dev/pktfifo.cc -# dev/platform.cc -# dev/sinic.cc -# dev/simple_disk.cc -# dev/tsunami.cc -# dev/tsunami_cchip.cc -# dev/isa_fake.cc -# dev/tsunami_io.cc -# dev/tsunami_pchip.cc -# dev/uart.cc -# dev/uart8250.cc -# -# kern/kernel_binning.cc -# kern/kernel_stats.cc -# kern/system_events.cc -# kern/freebsd/freebsd_system.cc -# kern/linux/linux_syscalls.cc -# kern/linux/linux_system.cc -# kern/linux/printk.cc -# kern/tru64/dump_mbuf.cc -# kern/tru64/printf.cc -# kern/tru64/tru64_events.cc -# kern/tru64/tru64_syscalls.cc -# kern/tru64/tru64_system.cc -# -# mem/functional/memory_control.cc -# mem/functional/physical.cc -# -# sim/system.cc -# ''') - -# turbolaser encumbered sources -arch_turbolaser_sources = Split(''' - ''') -# encumbered/dev/dma.cc -# encumbered/dev/etherdev.cc -# encumbered/dev/scsi.cc -# encumbered/dev/scsi_ctrl.cc -# encumbered/dev/scsi_disk.cc -# encumbered/dev/scsi_none.cc -# encumbered/dev/tlaser_clock.cc -# encumbered/dev/tlaser_ipi.cc -# encumbered/dev/tlaser_mbox.cc -# encumbered/dev/tlaser_mc146818.cc -# encumbered/dev/tlaser_node.cc -# encumbered/dev/tlaser_pcia.cc -# encumbered/dev/tlaser_pcidev.cc -# encumbered/dev/tlaser_serial.cc -# encumbered/dev/turbolaser.cc -# encumbered/dev/uart8530.cc -# ''') # Syscall emulation (non-full-system) sources -arch_syscall_emulation_sources = Split(''' - arch/alpha/alpha_common_syscall_emul.cc - arch/alpha/alpha_linux_process.cc - arch/alpha/alpha_tru64_process.cc +syscall_emulation_sources = Split(''' + alpha_common_syscall_emul.cc + alpha_linux_process.cc + alpha_tru64_process.cc ''') -# cpu/memtest/memtest.cc -# encumbered/eio/eio.cc -# encumbered/eio/exolex.cc -# encumbered/eio/libexo.cc -# sim/process.cc -# sim/syscall_emul.cc -# ''') - -#targetarch_files = Split(''' -# alpha_common_syscall_emul.hh -# alpha_linux_process.hh -# alpha_memory.hh -# alpha_tru64_process.hh -# aout_machdep.h -# arguments.hh -# byte_swap.hh -# ecoff_machdep.h -# ev5.hh -# faults.hh -# isa_fullsys_traits.hh -# isa_traits.hh -# osfpal.hh -# pseudo_inst.hh -# stacktrace.hh -# vptr.hh -# vtophys.hh -# ''') - -#for f in targetarch_files: -# env.Command('targetarch/' + f, 'arch/alpha/' + f, -# '''echo '#include "arch/alpha/%s"' > $TARGET''' % f) - # Set up complete list of sources based on configuration. -sources = arch_base_sources +sources = base_sources if env['FULL_SYSTEM']: - sources += arch_full_system_sources - if env['ALPHA_TLASER']: - sources += arch_turbolaser_sources + sources += full_system_sources else: - sources += arch_syscall_emulation_sources - -if env['USE_MYSQL']: - sources += arch_mysql_sources - -for opt in env.ExportOptions: - env.ConfigFile(opt) - -################################################### -# -# Special build rules. -# -################################################### - -# base/traceflags.{cc,hh} are generated from base/traceflags.py. -# $TARGET.base will expand to "<build-dir>/base/traceflags". -# env.Command(Split('base/traceflags.hh base/traceflags.cc'), -# 'base/traceflags.py', -# 'python $SOURCE $TARGET.base') - -# several files are generated from arch/$TARGET_ISA/isa_desc. -#env.Command(Split('''decoder.cc -# decoder.hh -# alpha_o3_exec.cc -# fast_cpu_exec.cc -# simple_cpu_exec.cc -# full_cpu_exec.cc'''), -# Split('''isa_desc -# ../isa_parser.py'''), -# '$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/alpha') - - -# libelf build is described in its own SConscript file. -# SConscript-local is the per-config build, which just copies some -# header files into a place where they can be found. -# SConscript('libelf/SConscript-local', exports = 'env', duplicate=0) -# SConscript('python/SConscript', exports = ['env'], duplicate=0) - -# This function adds the specified sources to the given build -# environment, and returns a list of all the corresponding SCons -# Object nodes (including an extra one for date.cc). We explicitly -# add the Object nodes so we can set up special dependencies for -# date.cc. -# def make_objs(sources, env): -# objs = [env.Object(s) for s in sources] -# # make date.cc depend on all other objects so it always gets -# # recompiled whenever anything else does -# date_obj = env.Object('base/date.cc') -# base/traceflags.{cc,hh} are generated from base/traceflags.py. -# $TARGET.base will expand to "<build-dir>/base/traceflags". -# env.Command(Split('base/traceflags.hh base/traceflags.cc'), -# 'base/traceflags.py', -# 'python $SOURCE $TARGET.base') -# -# Split('''arch/alpha/isa_desc -# arch/isa_parser.py'''), -# env.Depends(date_obj, objs) -# objs.append(date_obj) -# return objs - -################################################### -# -# Define binaries. Each different build type (debug, opt, etc.) gets -# a slightly different build environment. -# -################################################### - -# Include file paths are rooted in this directory. SCons will -# automatically expand '.' to refer to both the source directory and -# the corresponding build directory to pick up generated include -# files. -# env.Append(CPPPATH='.') - -# Debug binary -# debugEnv = env.Copy(OBJSUFFIX='.do') -# debugEnv.Label = 'debug' -# debugEnv.Append(CCFLAGS=Split('-g -gstabs+ -O0')) -# debugEnv.Append(CPPDEFINES='DEBUG') -# tlist = debugEnv.Program(target = 'm5.debug', -# source = make_objs(sources, debugEnv)) -# debugEnv.M5Binary = tlist[0] + sources += syscall_emulation_sources -# Optimized binary -# optEnv = env.Copy() -# optEnv.Label = 'opt' -# optEnv.Append(CCFLAGS=Split('-g -O5')) -# tlist = optEnv.Program(target = 'm5.opt', -# source = make_objs(sources, optEnv)) -# optEnv.M5Binary = tlist[0] +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] -# "Fast" binary -# fastEnv = env.Copy(OBJSUFFIX='.fo') -# fastEnv.Label = 'fast' -# fastEnv.Append(CCFLAGS=Split('-O5')) -# fastEnv.Append(CPPDEFINES='NDEBUG') -# fastEnv.Program(target = 'm5.fast.unstripped', -# source = make_objs(sources, fastEnv)) -# tlist = fastEnv.Command(target = 'm5.fast', -# source = 'm5.fast.unstripped', -# action = 'strip $SOURCE -o $TARGET') -# fastEnv.M5Binary = tlist[0] +# Add in files generated by the ISA description. +isa_desc_files = env.ISADesc('isa/main.isa') +# Only non-header files need to be compiled. +isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] +sources += isa_desc_sources -# Profiled binary -# profEnv = env.Copy(OBJSUFFIX='.po') -# profEnv.Label = 'prof' -# profEnv.Append(CCFLAGS=Split('-O5 -g -pg'), LINKFLAGS='-pg') -# tlist = profEnv.Program(target = 'm5.prof', -# source = make_objs(sources, profEnv)) -# profEnv.M5Binary = tlist[0] -# -# envList = [debugEnv, optEnv, fastEnv, profEnv] -# -# Return('envList') Return('sources') diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/alpha_linux_process.cc index fb5e32e63..16ebcca7b 100644 --- a/arch/alpha/alpha_linux_process.cc +++ b/arch/alpha/alpha_linux_process.cc @@ -26,506 +26,122 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> // for host open() flags -#include <string.h> // for memset() -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> +#include "arch/alpha/alpha_common_syscall_emul.hh" +#include "arch/alpha/alpha_linux_process.hh" +#include "arch/alpha/isa_traits.hh" -#include "cpu/base.hh" +#include "base/trace.hh" #include "cpu/exec_context.hh" +#include "kern/linux/linux.hh" #include "mem/functional/functional.hh" -#include "sim/fake_syscall.hh" -#include "sim/host.hh" -#include "sim/process.hh" -#include "sim/sim_events.hh" -#include "arch/alpha/isa_traits.hh" -#include "arch/alpha/alpha_common_syscall_emul.hh" +#include "sim/process.hh" #include "sim/syscall_emul.hh" -#include "sim/root.hh" // for curTick & ticksPerSecond - -#include "arch/alpha/alpha_linux_process.hh" - -#include "base/trace.hh" using namespace std; +using namespace AlphaISA; + +/// Target pipe() handler. Even though this is a generic Posix call, +/// the Alpha return convention is funky, so that makes it +/// Alpha-specific. +SyscallReturn +pipeFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + int fds[2], sim_fds[2]; + int pipe_retval = pipe(fds); -/// -/// This class encapsulates the types, structures, constants, -/// functions, and syscall-number mappings specific to the Alpha Linux -/// syscall interface. -/// -class Linux { - - public: - - //@{ - /// Basic Linux types. - typedef uint64_t size_t; - typedef uint64_t off_t; - typedef int64_t time_t; - typedef uint32_t uid_t; - typedef uint32_t gid_t; - //@} - -#if BSD_HOST - typedef struct stat hst_stat; - typedef struct stat hst_stat64; -#else - typedef struct stat hst_stat ; - typedef struct stat64 hst_stat64; -#endif - - - //@{ - /// open(2) flag values. - static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 00000002; //!< O_RDWR - static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK - static const int TGT_O_APPEND = 00000010; //!< O_APPEND - static const int TGT_O_CREAT = 00001000; //!< O_CREAT - static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC - static const int TGT_O_EXCL = 00004000; //!< O_EXCL - static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY - static const int TGT_O_SYNC = 00040000; //!< O_SYNC - static const int TGT_O_DRD = 00100000; //!< O_DRD - static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO - static const int TGT_O_CACHE = 00400000; //!< O_CACHE - static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC - static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC - //@} - - /// This table maps the target open() flags to the corresponding - /// host open() flags. - static OpenFlagTransTable openFlagTable[]; - - /// Number of entries in openFlagTable[]. - static const int NUM_OPEN_FLAGS; - - /// Stat buffer. Note that we can't call it 'stat' since that - /// gets #defined to something else on some systems. - struct tgt_stat { - uint32_t st_dev; //!< device - uint32_t st_ino; //!< inode - uint32_t st_mode; //!< mode - uint32_t st_nlink; //!< link count - uint32_t st_uid; //!< owner's user ID - uint32_t st_gid; //!< owner's group ID - uint32_t st_rdev; //!< device number - int32_t _pad1; //!< for alignment - int64_t st_size; //!< file size in bytes - uint64_t st_atimeX; //!< time of last access - uint64_t st_mtimeX; //!< time of last modification - uint64_t st_ctimeX; //!< time of last status change - uint32_t st_blksize; //!< optimal I/O block size - int32_t st_blocks; //!< number of blocks allocated - uint32_t st_flags; //!< flags - uint32_t st_gen; //!< unknown - }; - - // same for stat64 - struct tgt_stat64 { - uint64_t st_dev; - uint64_t st_ino; - uint64_t st_rdev; - int64_t st_size; - uint64_t st_blocks; - - uint32_t st_mode; - uint32_t st_uid; - uint32_t st_gid; - uint32_t st_blksize; - uint32_t st_nlink; - uint32_t __pad0; - - uint64_t tgt_st_atime; - uint64_t st_atime_nsec; - uint64_t tgt_st_mtime; - uint64_t st_mtime_nsec; - uint64_t tgt_st_ctime; - uint64_t st_ctime_nsec; - int64_t ___unused[3]; - }; - - /// Length of strings in struct utsname (plus 1 for null char). - static const int _SYS_NMLN = 65; - - /// Interface struct for uname(). - struct utsname { - char sysname[_SYS_NMLN]; //!< System name. - char nodename[_SYS_NMLN]; //!< Node name. - char release[_SYS_NMLN]; //!< OS release. - char version[_SYS_NMLN]; //!< OS version. - char machine[_SYS_NMLN]; //!< Machine type. - }; - - - //@{ - /// ioctl() command codes. - static const unsigned TIOCGETP = 0x40067408; - static const unsigned TIOCSETP = 0x80067409; - static const unsigned TIOCSETN = 0x8006740a; - static const unsigned TIOCSETC = 0x80067411; - static const unsigned TIOCGETC = 0x40067412; - static const unsigned FIONREAD = 0x4004667f; - static const unsigned TIOCISATTY = 0x2000745e; - static const unsigned TIOCGETS = 0x402c7413; - static const unsigned TIOCGETA = 0x40127417; - //@} - - /// Resource enumeration for getrlimit(). - enum rlimit_resources { - TGT_RLIMIT_CPU = 0, - TGT_RLIMIT_FSIZE = 1, - TGT_RLIMIT_DATA = 2, - TGT_RLIMIT_STACK = 3, - TGT_RLIMIT_CORE = 4, - TGT_RLIMIT_RSS = 5, - TGT_RLIMIT_NOFILE = 6, - TGT_RLIMIT_AS = 7, - TGT_RLIMIT_VMEM = 7, - TGT_RLIMIT_NPROC = 8, - TGT_RLIMIT_MEMLOCK = 9, - TGT_RLIMIT_LOCKS = 10 - }; - - /// Limit struct for getrlimit/setrlimit. - struct rlimit { - uint64_t rlim_cur; //!< soft limit - uint64_t rlim_max; //!< hard limit - }; - - - /// For mmap(). - static const unsigned TGT_MAP_ANONYMOUS = 0x10; - - /// For gettimeofday(). - struct timeval { - int64_t tv_sec; //!< seconds - int64_t tv_usec; //!< microseconds - }; - - // For writev/readv - struct tgt_iovec { - uint64_t iov_base; // void * - uint64_t iov_len; - }; - - //@{ - /// For getrusage(). - static const int TGT_RUSAGE_SELF = 0; - static const int TGT_RUSAGE_CHILDREN = -1; - static const int TGT_RUSAGE_BOTH = -2; - //@} - - /// For getrusage(). - struct rusage { - struct timeval ru_utime; //!< user time used - struct timeval ru_stime; //!< system time used - int64_t ru_maxrss; //!< max rss - int64_t ru_ixrss; //!< integral shared memory size - int64_t ru_idrss; //!< integral unshared data " - int64_t ru_isrss; //!< integral unshared stack " - int64_t ru_minflt; //!< page reclaims - total vmfaults - int64_t ru_majflt; //!< page faults - int64_t ru_nswap; //!< swaps - int64_t ru_inblock; //!< block input operations - int64_t ru_oublock; //!< block output operations - int64_t ru_msgsnd; //!< messages sent - int64_t ru_msgrcv; //!< messages received - int64_t ru_nsignals; //!< signals received - int64_t ru_nvcsw; //!< voluntary context switches - int64_t ru_nivcsw; //!< involuntary " - }; - - /// Helper function to convert a host stat buffer to a target stat - /// buffer. Also copies the target buffer out to the simulated - /// memory space. Used by stat(), fstat(), and lstat(). -#if !BSD_HOST - static void - copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host) - { - TypedBufferArg<Linux::tgt_stat> tgt(addr); - - tgt->st_dev = htog(host->st_dev); - tgt->st_ino = htog(host->st_ino); - tgt->st_mode = htog(host->st_mode); - tgt->st_nlink = htog(host->st_nlink); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_atimeX = htog(host->st_atime); - tgt->st_mtimeX = htog(host->st_mtime); - tgt->st_ctimeX = htog(host->st_ctime); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_blocks = htog(host->st_blocks); - - tgt.copyOut(mem); - } -#else - // Third version for bsd systems which no longer have any support for - // the old stat() call and stat() is actually a stat64() - static void - copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host) - { - TypedBufferArg<Linux::tgt_stat> tgt(addr); - - tgt->st_dev = htog(host->st_dev); - tgt->st_ino = htog(host->st_ino); - tgt->st_mode = htog(host->st_mode); - tgt->st_nlink = htog(host->st_nlink); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_atimeX = htog(host->st_atime); - tgt->st_mtimeX = htog(host->st_mtime); - tgt->st_ctimeX = htog(host->st_ctime); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_blocks = htog(host->st_blocks); - - tgt.copyOut(mem); - } -#endif - - - // Same for stat64 - static void - copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host) - { - TypedBufferArg<Linux::tgt_stat64> tgt(addr); - - // fd == 1 checks are because libc does some checks - // that the stdout is interactive vs. a file - // this makes it work on non-linux systems - if (fd == 1) - tgt->st_dev = htog((uint64_t)0xA); - else - tgt->st_dev = htog((uint64_t)host->st_dev); - // XXX What about STAT64_HAS_BROKEN_ST_INO ??? - tgt->st_ino = htog((uint64_t)host->st_ino); - if (fd == 1) - tgt->st_rdev = htog((uint64_t)0x880d); - else - tgt->st_rdev = htog((uint64_t)host->st_rdev); - tgt->st_size = htog((int64_t)host->st_size); - tgt->st_blocks = htog((uint64_t)host->st_blocks); - - if (fd == 1) - tgt->st_mode = htog((uint32_t)0x2190); - else - tgt->st_mode = htog((uint32_t)host->st_mode); - tgt->st_uid = htog((uint32_t)host->st_uid); - tgt->st_gid = htog((uint32_t)host->st_gid); - tgt->st_blksize = htog((uint32_t)host->st_blksize); - tgt->st_nlink = htog((uint32_t)host->st_nlink); - tgt->tgt_st_atime = htog((uint64_t)host->st_atime); - tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime); - tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime); -#if defined(STAT_HAVE_NSEC) - tgt->st_atime_nsec = htog(host->st_atime_nsec); - tgt->st_mtime_nsec = htog(host->st_mtime_nsec); - tgt->st_ctime_nsec = htog(host->st_ctime_nsec); -#else - tgt->st_atime_nsec = 0; - tgt->st_mtime_nsec = 0; - tgt->st_ctime_nsec = 0; -#endif - - tgt.copyOut(mem); - } - - /// The target system's hostname. - static const char *hostname; - - /// Target uname() handler. - static SyscallReturn - unameFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0)); - - strcpy(name->sysname, "Linux"); - strcpy(name->nodename, hostname); - strcpy(name->release, "2.4.20"); - strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); - strcpy(name->machine, "alpha"); - - name.copyOut(xc->mem); - return 0; - } - - /// Target osf_getsysyinfo() handler. Even though this call is - /// borrowed from Tru64, the subcases that get used appear to be - /// different in practice from those used by Tru64 processes. - static SyscallReturn - osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - unsigned op = xc->getSyscallArg(0); - // unsigned nbytes = xc->getSyscallArg(2); - - switch (op) { - - case 45: { // GSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); - // I don't think this exactly matches the HW FPCR - *fpcr = 0; - fpcr.copyOut(xc->mem); - return 0; - } - - default: - cerr << "osf_getsysinfo: unknown op " << op << endl; - abort(); - break; - } - - return 1; - } - - /// Target osf_setsysinfo() handler. - static SyscallReturn - osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - unsigned op = xc->getSyscallArg(0); - // unsigned nbytes = xc->getSyscallArg(2); - - switch (op) { - - case 14: { // SSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); - // I don't think this exactly matches the HW FPCR - fpcr.copyIn(xc->mem); - DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " - " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); - return 0; - } - - default: - cerr << "osf_setsysinfo: unknown op " << op << endl; - abort(); - break; - } - - return 1; + if (pipe_retval < 0) { + // error + return pipe_retval; } - /// Target fnctl() handler. - static SyscallReturn - fcntlFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - int fd = xc->getSyscallArg(0); + sim_fds[0] = process->alloc_fd(fds[0]); + sim_fds[1] = process->alloc_fd(fds[1]); - if (fd < 0 || process->sim_fd(fd) < 0) - return -EBADF; + // Alpha Linux convention for pipe() is that fd[0] is returned as + // the return value of the function, and fd[1] is returned in r20. + xc->regs.intRegFile[20] = sim_fds[1]; + return sim_fds[0]; +} - int cmd = xc->getSyscallArg(1); - switch (cmd) { - case 0: // F_DUPFD - // if we really wanted to support this, we'd need to do it - // in the target fd space. - warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); - return -EMFILE; - case 1: // F_GETFD (get close-on-exec flag) - case 2: // F_SETFD (set close-on-exec flag) - return 0; +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0)); - case 3: // F_GETFL (get file flags) - case 4: // F_SETFL (set file flags) - // not sure if this is totally valid, but we'll pass it through - // to the underlying OS - warn("fcntl(%d, %d) passed through to host\n", fd, cmd); - return fcntl(process->sim_fd(fd), cmd); - // return 0; + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.4.20"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "alpha"); - case 7: // F_GETLK (get lock) - case 8: // F_SETLK (set lock) - case 9: // F_SETLKW (set lock and wait) - // don't mess with file locking... just act like it's OK - warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); - return 0; + name.copyOut(xc->mem); + return 0; +} - default: - warn("Unknown fcntl command %d\n", cmd); - return 0; - } +/// Target osf_getsysyinfo() handler. Even though this call is +/// borrowed from Tru64, the subcases that get used appear to be +/// different in practice from those used by Tru64 processes. +static SyscallReturn +osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + // unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case 45: { // GSI_IEEE_FP_CONTROL + TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); + // I don't think this exactly matches the HW FPCR + *fpcr = 0; + fpcr.copyOut(xc->mem); + return 0; + } + + default: + cerr << "osf_getsysinfo: unknown op " << op << endl; + abort(); + break; } - /// Array of syscall descriptors, indexed by call number. - static SyscallDesc syscallDescs[]; - - /// Number of syscalls in syscallDescs[]. - static const int Num_Syscall_Descs; - - /// Max supported syscall number. - static const int Max_Syscall_Desc; - - /// Do the specified syscall. Just looks the call number up in - /// the table and invokes the appropriate handler. - static void - doSyscall(int callnum, Process *process, ExecContext *xc) - { - if (callnum < 0 || callnum > Max_Syscall_Desc) { - fatal("Syscall %d out of range", callnum); - } - - SyscallDesc *desc = &syscallDescs[callnum]; + return 1; +} - desc->doSyscall(callnum, process, xc); +/// Target osf_setsysinfo() handler. +static SyscallReturn +osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + // unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case 14: { // SSI_IEEE_FP_CONTROL + TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); + // I don't think this exactly matches the HW FPCR + fpcr.copyIn(xc->mem); + DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " + " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); + return 0; + } + + default: + cerr << "osf_setsysinfo: unknown op " << op << endl; + abort(); + break; } -}; // class Linux - -// open(2) flags translation table -OpenFlagTransTable Linux::openFlagTable[] = { -#ifdef _MSC_VER - { Linux::TGT_O_RDONLY, _O_RDONLY }, - { Linux::TGT_O_WRONLY, _O_WRONLY }, - { Linux::TGT_O_RDWR, _O_RDWR }, - { Linux::TGT_O_APPEND, _O_APPEND }, - { Linux::TGT_O_CREAT, _O_CREAT }, - { Linux::TGT_O_TRUNC, _O_TRUNC }, - { Linux::TGT_O_EXCL, _O_EXCL }, -#ifdef _O_NONBLOCK - { Linux::TGT_O_NONBLOCK, _O_NONBLOCK }, -#endif -#ifdef _O_NOCTTY - { Linux::TGT_O_NOCTTY, _O_NOCTTY }, -#endif -#ifdef _O_SYNC - { Linux::TGT_O_SYNC, _O_SYNC }, -#endif -#else /* !_MSC_VER */ - { Linux::TGT_O_RDONLY, O_RDONLY }, - { Linux::TGT_O_WRONLY, O_WRONLY }, - { Linux::TGT_O_RDWR, O_RDWR }, - { Linux::TGT_O_APPEND, O_APPEND }, - { Linux::TGT_O_CREAT, O_CREAT }, - { Linux::TGT_O_TRUNC, O_TRUNC }, - { Linux::TGT_O_EXCL, O_EXCL }, - { Linux::TGT_O_NONBLOCK, O_NONBLOCK }, - { Linux::TGT_O_NOCTTY, O_NOCTTY }, -#ifdef O_SYNC - { Linux::TGT_O_SYNC, O_SYNC }, -#endif -#endif /* _MSC_VER */ -}; - -const int Linux::NUM_OPEN_FLAGS = - (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0])); + return 1; +} -const char *Linux::hostname = "m5.eecs.umich.edu"; -SyscallDesc Linux::syscallDescs[] = { +SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc), /* 1 */ SyscallDesc("exit", exitFunc), /* 2 */ SyscallDesc("fork", unimplementedFunc), @@ -568,7 +184,7 @@ SyscallDesc Linux::syscallDescs[] = { /* 39 */ SyscallDesc("setpgid", unimplementedFunc), /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc), /* 41 */ SyscallDesc("dup", unimplementedFunc), - /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipeFunc), /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc), /* 44 */ SyscallDesc("osf_profil", unimplementedFunc), /* 45 */ SyscallDesc("open", openFunc<Linux>), @@ -973,23 +589,6 @@ SyscallDesc Linux::syscallDescs[] = { /* 441 */ SyscallDesc("keyctl", unimplementedFunc) }; -const int Linux::Num_Syscall_Descs = - sizeof(Linux::syscallDescs) / sizeof(SyscallDesc); - -const int Linux::Max_Syscall_Desc = Linux::Num_Syscall_Descs - 1; - - -void -AlphaLinuxProcess::syscall(ExecContext *xc) -{ - num_syscalls++; - - int64_t callnum = xc->regs.intRegFile[ReturnValueReg]; - - Linux::doSyscall(callnum, this, xc); -} - - AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name, ObjectFile *objFile, int stdin_fd, @@ -997,7 +596,18 @@ AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) - : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp) + : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) { init_regs->intRegFile[0] = 0; } + + + +SyscallDesc* +AlphaLinuxProcess::getDesc(int callnum) +{ + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + return &syscallDescs[callnum]; +} diff --git a/arch/alpha/alpha_linux_process.hh b/arch/alpha/alpha_linux_process.hh index b4fe8e8f8..7de1b1ac1 100644 --- a/arch/alpha/alpha_linux_process.hh +++ b/arch/alpha/alpha_linux_process.hh @@ -43,8 +43,15 @@ class AlphaLinuxProcess : public LiveProcess std::vector<std::string> &argv, std::vector<std::string> &envp); - /// Syscall emulation function. - virtual void syscall(ExecContext *xc); + virtual SyscallDesc* getDesc(int callnum); + + /// The target system's hostname. + static const char *hostname; + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + const int Num_Syscall_Descs; }; diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index 8dda4d9c4..d00186d95 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -312,7 +312,7 @@ AlphaITB::translate(MemReqPtr &req) const // strip off PAL PC marker (lsb is 1) req->paddr = (req->vaddr & ~3) & PAddrImplMask; hits++; - return No_Fault; + return NoFault; } if (req->flags & PHYSICAL) { @@ -322,7 +322,7 @@ AlphaITB::translate(MemReqPtr &req) const if (!validVirtualAddress(req->vaddr)) { fault(req->vaddr, req->xc); acv++; - return ITB_Acv_Fault; + return ItbAcvFault; } @@ -339,7 +339,7 @@ AlphaITB::translate(MemReqPtr &req) const AlphaISA::mode_kernel) { fault(req->vaddr, req->xc); acv++; - return ITB_Acv_Fault; + return ItbAcvFault; } req->paddr = req->vaddr & PAddrImplMask; @@ -360,7 +360,7 @@ AlphaITB::translate(MemReqPtr &req) const if (!pte) { fault(req->vaddr, req->xc); misses++; - return ITB_Fault_Fault; + return ItbPageFault; } req->paddr = (pte->ppn << AlphaISA::PageShift) + @@ -371,7 +371,7 @@ AlphaITB::translate(MemReqPtr &req) const // instruction access fault fault(req->vaddr, req->xc); acv++; - return ITB_Acv_Fault; + return ItbAcvFault; } hits++; @@ -380,11 +380,11 @@ AlphaITB::translate(MemReqPtr &req) const // check that the physical address is ok (catch bad physical addresses) if (req->paddr & ~PAddrImplMask) - return Machine_Check_Fault; + return MachineCheckFault; checkCacheability(req); - return No_Fault; + return NoFault; } /////////////////////////////////////////////////////////////////////// @@ -511,7 +511,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const fault(req, write ? MM_STAT_WR_MASK : 0); DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr, req->size); - return Alignment_Fault; + return AlignmentFault; } if (pc & 0x1) { @@ -530,7 +530,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const MM_STAT_ACV_MASK); if (write) { write_acv++; } else { read_acv++; } - return DTB_Fault_Fault; + return DtbPageFault; } // Check for "superpage" mapping @@ -547,7 +547,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK)); if (write) { write_acv++; } else { read_acv++; } - return DTB_Acv_Fault; + return DtbAcvFault; } req->paddr = req->vaddr & PAddrImplMask; @@ -575,7 +575,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const fault(req, (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK); if (write) { write_misses++; } else { read_misses++; } - return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault; + return (req->flags & VPTE) ? (Fault)PDtbMissFault : (Fault)NDtbMissFault; } req->paddr = (pte->ppn << AlphaISA::PageShift) + @@ -588,25 +588,25 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const MM_STAT_ACV_MASK | (pte->fonw ? MM_STAT_FONW_MASK : 0)); write_acv++; - return DTB_Fault_Fault; + return DtbPageFault; } if (pte->fonw) { fault(req, MM_STAT_WR_MASK | MM_STAT_FONW_MASK); write_acv++; - return DTB_Fault_Fault; + return DtbPageFault; } } else { if (!(pte->xre & MODE2MASK(mode))) { fault(req, MM_STAT_ACV_MASK | (pte->fonr ? MM_STAT_FONR_MASK : 0)); read_acv++; - return DTB_Acv_Fault; + return DtbAcvFault; } if (pte->fonr) { fault(req, MM_STAT_FONR_MASK); read_acv++; - return DTB_Fault_Fault; + return DtbPageFault; } } } @@ -619,11 +619,11 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const // check that the physical address is ok (catch bad physical addresses) if (req->paddr & ~PAddrImplMask) - return Machine_Check_Fault; + return MachineCheckFault; checkCacheability(req); - return No_Fault; + return NoFault; } AlphaISA::PTE & diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh index 788923434..de955fa46 100644 --- a/arch/alpha/alpha_memory.hh +++ b/arch/alpha/alpha_memory.hh @@ -32,6 +32,7 @@ #include <map> #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/faults.hh" #include "base/statistics.hh" #include "mem/mem_req.hh" #include "sim/sim_object.hh" diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc index 5c24adad9..8121d3452 100644 --- a/arch/alpha/alpha_tru64_process.cc +++ b/arch/alpha/alpha_tru64_process.cc @@ -26,1532 +26,139 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/types.h> -#include <sys/stat.h> -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__) -#include <sys/param.h> -#include <sys/mount.h> -#else -#include <sys/statfs.h> -#endif - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> // for host open() flags -#include <string.h> // for memset() -#include <unistd.h> - #include "arch/alpha/isa_traits.hh" #include "arch/alpha/alpha_common_syscall_emul.hh" #include "arch/alpha/alpha_tru64_process.hh" -#include "base/trace.hh" -#include "cpu/base.hh" #include "cpu/exec_context.hh" +#include "kern/tru64/tru64.hh" #include "mem/functional/functional.hh" #include "sim/fake_syscall.hh" -#include "sim/host.hh" #include "sim/process.hh" -#include "sim/root.hh" #include "sim/syscall_emul.hh" using namespace std; +using namespace AlphaISA; -typedef struct stat global_stat; -typedef struct statfs global_statfs; -typedef struct dirent global_dirent; - -/// -/// This class encapsulates the types, structures, constants, -/// functions, and syscall-number mappings specific to the Alpha Tru64 -/// syscall interface. -/// -class Tru64 { - - public: - - //@{ - /// Basic Tru64 types. - typedef uint64_t size_t; - typedef uint64_t off_t; - typedef uint16_t nlink_t; - typedef int32_t dev_t; - typedef uint32_t uid_t; - typedef uint32_t gid_t; - typedef uint32_t time_t; - typedef uint32_t mode_t; - typedef uint32_t ino_t; - typedef struct { int val[2]; } quad; - typedef quad fsid_t; - //@} - - //@{ - /// open(2) flag values. - static const int TGT_O_RDONLY = 00000000; - static const int TGT_O_WRONLY = 00000001; - static const int TGT_O_RDWR = 00000002; - static const int TGT_O_NONBLOCK = 00000004; - static const int TGT_O_APPEND = 00000010; - static const int TGT_O_CREAT = 00001000; - static const int TGT_O_TRUNC = 00002000; - static const int TGT_O_EXCL = 00004000; - static const int TGT_O_NOCTTY = 00010000; - static const int TGT_O_SYNC = 00040000; - static const int TGT_O_DRD = 00100000; - static const int TGT_O_DIRECTIO = 00200000; - static const int TGT_O_CACHE = 00400000; - static const int TGT_O_DSYNC = 02000000; - static const int TGT_O_RSYNC = 04000000; - //@} - - /// This table maps the target open() flags to the corresponding - /// host open() flags. - static OpenFlagTransTable openFlagTable[]; - - /// Number of entries in openFlagTable[]. - static const int NUM_OPEN_FLAGS; - - /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat - /// structure, and a new set of syscall numbers for stat calls. - /// On some hosts (notably Linux) define st_atime, st_mtime, and - /// st_ctime as macros, so we append an X to get around this. - struct F64_stat { - dev_t st_dev; //!< st_dev - int32_t st_retired1; //!< st_retired1 - mode_t st_mode; //!< st_mode - nlink_t st_nlink; //!< st_nlink - uint16_t st_nlink_reserved; //!< st_nlink_reserved - uid_t st_uid; //!< st_uid - gid_t st_gid; //!< st_gid - dev_t st_rdev; //!< st_rdev - dev_t st_ldev; //!< st_ldev - off_t st_size; //!< st_size - time_t st_retired2; //!< st_retired2 - int32_t st_uatime; //!< st_uatime - time_t st_retired3; //!< st_retired3 - int32_t st_umtime; //!< st_umtime - time_t st_retired4; //!< st_retired4 - int32_t st_uctime; //!< st_uctime - int32_t st_retired5; //!< st_retired5 - int32_t st_retired6; //!< st_retired6 - uint32_t st_flags; //!< st_flags - uint32_t st_gen; //!< st_gen - uint64_t st_spare[4]; //!< st_spare[4] - ino_t st_ino; //!< st_ino - int32_t st_ino_reserved; //!< st_ino_reserved - time_t st_atimeX; //!< st_atime - int32_t st_atime_reserved; //!< st_atime_reserved - time_t st_mtimeX; //!< st_mtime - int32_t st_mtime_reserved; //!< st_mtime_reserved - time_t st_ctimeX; //!< st_ctime - int32_t st_ctime_reserved; //!< st_ctime_reserved - uint64_t st_blksize; //!< st_blksize - uint64_t st_blocks; //!< st_blocks - }; - - - /// Old Tru64 v4.x stat struct. - /// Tru64 maintains backwards compatibility with v4.x by - /// implementing another set of stat functions using the old - /// structure definition and binding them to the old syscall - /// numbers. - struct pre_F64_stat { - dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; - off_t st_size; - time_t st_atimeX; - int32_t st_uatime; - time_t st_mtimeX; - int32_t st_umtime; - time_t st_ctimeX; - int32_t st_uctime; - uint32_t st_blksize; - int32_t st_blocks; - uint32_t st_flags; - uint32_t st_gen; - }; - - /// For statfs(). - struct F64_statfs { - int16_t f_type; - int16_t f_flags; - int32_t f_retired1; - int32_t f_retired2; - int32_t f_retired3; - int32_t f_retired4; - int32_t f_retired5; - int32_t f_retired6; - int32_t f_retired7; - fsid_t f_fsid; - int32_t f_spare[9]; - char f_retired8[90]; - char f_retired9[90]; - uint64_t dummy[10]; // was union mount_info mount_info; - uint64_t f_flags2; - int64_t f_spare2[14]; - int64_t f_fsize; - int64_t f_bsize; - int64_t f_blocks; - int64_t f_bfree; - int64_t f_bavail; - int64_t f_files; - int64_t f_ffree; - char f_mntonname[1024]; - char f_mntfromname[1024]; - }; - - /// For old Tru64 v4.x statfs() - struct pre_F64_statfs { - int16_t f_type; - int16_t f_flags; - int32_t f_fsize; - int32_t f_bsize; - int32_t f_blocks; - int32_t f_bfree; - int32_t f_bavail; - int32_t f_files; - int32_t f_ffree; - fsid_t f_fsid; - int32_t f_spare[9]; - char f_mntonname[90]; - char f_mntfromname[90]; - uint64_t dummy[10]; // was union mount_info mount_info; - }; - - /// For getdirentries(). - struct dirent - { - ino_t d_ino; //!< file number of entry - uint16_t d_reclen; //!< length of this record - uint16_t d_namlen; //!< length of string in d_name - char d_name[256]; //!< dummy name length - }; - - - /// Length of strings in struct utsname (plus 1 for null char). - static const int _SYS_NMLN = 32; - - /// Interface struct for uname(). - struct utsname { - char sysname[_SYS_NMLN]; //!< System name. - char nodename[_SYS_NMLN]; //!< Node name. - char release[_SYS_NMLN]; //!< OS release. - char version[_SYS_NMLN]; //!< OS version. - char machine[_SYS_NMLN]; //!< Machine type. - }; - - //@{ - /// ioctl() command codes. - static const unsigned TIOCGETP = 0x40067408; - static const unsigned TIOCSETP = 0x80067409; - static const unsigned TIOCSETN = 0x8006740a; - static const unsigned TIOCSETC = 0x80067411; - static const unsigned TIOCGETC = 0x40067412; - static const unsigned FIONREAD = 0x4004667f; - static const unsigned TIOCISATTY = 0x2000745e; - // TIOCGETS not defined in tru64, so I made up a number - static const unsigned TIOCGETS = 0x40000000; - static const unsigned TIOCGETA = 0x402c7413; - //@} - - /// Resource enumeration for getrlimit(). - enum rlimit_resources { - TGT_RLIMIT_CPU = 0, - TGT_RLIMIT_FSIZE = 1, - TGT_RLIMIT_DATA = 2, - TGT_RLIMIT_STACK = 3, - TGT_RLIMIT_CORE = 4, - TGT_RLIMIT_RSS = 5, - TGT_RLIMIT_NOFILE = 6, - TGT_RLIMIT_AS = 7, - TGT_RLIMIT_VMEM = 7 - }; - - /// Limit struct for getrlimit/setrlimit. - struct rlimit { - uint64_t rlim_cur; //!< soft limit - uint64_t rlim_max; //!< hard limit - }; - - - /// For mmap(). - static const unsigned TGT_MAP_ANONYMOUS = 0x10; - - - //@{ - /// For getsysinfo(). - static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type - static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz - //@} - - /// For getsysinfo() GSI_CPU_INFO option. - struct cpu_info { - uint32_t current_cpu; //!< current_cpu - uint32_t cpus_in_box; //!< cpus_in_box - uint32_t cpu_type; //!< cpu_type - uint32_t ncpus; //!< ncpus - uint64_t cpus_present; //!< cpus_present - uint64_t cpus_running; //!< cpus_running - uint64_t cpu_binding; //!< cpu_binding - uint64_t cpu_ex_binding; //!< cpu_ex_binding - uint32_t mhz; //!< mhz - uint32_t unused[3]; //!< future expansion - }; - - //@{ - /// For setsysinfo(). - static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() - //@} - - /// For gettimeofday. - struct timeval { - uint32_t tv_sec; //!< seconds - uint32_t tv_usec; //!< microseconds - }; - - //@{ - /// For getrusage(). - static const int TGT_RUSAGE_THREAD = 1; - static const int TGT_RUSAGE_SELF = 0; - static const int TGT_RUSAGE_CHILDREN = -1; - //@} - - /// For getrusage(). - struct rusage { - struct timeval ru_utime; //!< user time used - struct timeval ru_stime; //!< system time used - uint64_t ru_maxrss; //!< ru_maxrss - uint64_t ru_ixrss; //!< integral shared memory size - uint64_t ru_idrss; //!< integral unshared data " - uint64_t ru_isrss; //!< integral unshared stack " - uint64_t ru_minflt; //!< page reclaims - total vmfaults - uint64_t ru_majflt; //!< page faults - uint64_t ru_nswap; //!< swaps - uint64_t ru_inblock; //!< block input operations - uint64_t ru_oublock; //!< block output operations - uint64_t ru_msgsnd; //!< messages sent - uint64_t ru_msgrcv; //!< messages received - uint64_t ru_nsignals; //!< signals received - uint64_t ru_nvcsw; //!< voluntary context switches - uint64_t ru_nivcsw; //!< involuntary " - }; - - /// For sigreturn(). - struct sigcontext { - int64_t sc_onstack; //!< sigstack state to restore - int64_t sc_mask; //!< signal mask to restore - int64_t sc_pc; //!< pc at time of signal - int64_t sc_ps; //!< psl to retore - int64_t sc_regs[32]; //!< processor regs 0 to 31 - int64_t sc_ownedfp; //!< fp has been used - int64_t sc_fpregs[32]; //!< fp regs 0 to 31 - uint64_t sc_fpcr; //!< floating point control reg - uint64_t sc_fp_control; //!< software fpcr - int64_t sc_reserved1; //!< reserved for kernel - uint32_t sc_kreserved1; //!< reserved for kernel - uint32_t sc_kreserved2; //!< reserved for kernel - size_t sc_ssize; //!< stack size - caddr_t sc_sbase; //!< stack start - uint64_t sc_traparg_a0; //!< a0 argument to trap on exc - uint64_t sc_traparg_a1; //!< a1 argument to trap on exc - uint64_t sc_traparg_a2; //!< a2 argument to trap on exc - uint64_t sc_fp_trap_pc; //!< imprecise pc - uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg - uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc - }; - - - /// For table(). - static const int TBL_SYSINFO = 12; - - /// For table(). - struct tbl_sysinfo { - uint64_t si_user; //!< User time - uint64_t si_nice; //!< Nice time - uint64_t si_sys; //!< System time - uint64_t si_idle; //!< Idle time - uint64_t si_hz; //!< hz - uint64_t si_phz; //!< phz - uint64_t si_boottime; //!< Boot time in seconds - uint64_t wait; //!< Wait time - uint32_t si_max_procs; //!< rpb->rpb_numprocs - uint32_t pad; //!< padding - }; - - - /// For stack_create. - struct vm_stack { - // was void * - Addr address; //!< address hint - size_t rsize; //!< red zone size - size_t ysize; //!< yellow zone size - size_t gsize; //!< green zone size - size_t swap; //!< amount of swap to reserve - size_t incr; //!< growth increment - uint64_t align; //!< address alignment - uint64_t flags; //!< MAP_FIXED etc. - // was struct memalloc_attr * - Addr attr; //!< allocation policy - uint64_t reserved; //!< reserved - }; - - /// Return values for nxm calls. - enum { - KERN_NOT_RECEIVER = 7, - KERN_NOT_IN_SET = 12 - }; - - /// For nxm_task_init. - static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP - - /// Task attribute structure. - struct nxm_task_attr { - int64_t nxm_callback; //!< nxm_callback - unsigned int nxm_version; //!< nxm_version - unsigned short nxm_uniq_offset; //!< nxm_uniq_offset - unsigned short flags; //!< flags - int nxm_quantum; //!< nxm_quantum - int pad1; //!< pad1 - int64_t pad2; //!< pad2 - }; - - /// Signal set. - typedef uint64_t sigset_t; - - /// Thread state shared between user & kernel. - struct ushared_state { - sigset_t sigmask; //!< thread signal mask - sigset_t sig; //!< thread pending mask - // struct nxm_pth_state * - Addr pth_id; //!< out-of-line state - int flags; //!< shared flags -#define US_SIGSTACK 0x1 // thread called sigaltstack -#define US_ONSTACK 0x2 // thread is running on altstack -#define US_PROFILE 0x4 // thread called profil -#define US_SYSCALL 0x8 // thread in syscall -#define US_TRAP 0x10 // thread has trapped -#define US_YELLOW 0x20 // thread has mellowed yellow -#define US_YZONE 0x40 // thread has zoned out -#define US_FP_OWNED 0x80 // thread used floating point - - int cancel_state; //!< thread's cancelation state -#define US_CANCEL 0x1 // cancel pending -#define US_NOCANCEL 0X2 // synch cancel disabled -#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled -#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled -#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL) -#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \ - US_ASYNC_NOCANCEL) - - // These are semi-shared. They are always visible to - // the kernel but are never context-switched by the library. - - int nxm_ssig; //!< scheduler's synchronous signals - int reserved1; //!< reserved1 - int64_t nxm_active; //!< scheduler active - int64_t reserved2; //!< reserved2 - }; - - struct nxm_sched_state { - struct ushared_state nxm_u; //!< state own by user thread - unsigned int nxm_bits; //!< scheduler state / slot - int nxm_quantum; //!< quantum count-down value - int nxm_set_quantum; //!< quantum reset value - int nxm_sysevent; //!< syscall state - // struct nxm_upcall * - Addr nxm_uc_ret; //!< stack ptr of null thread - // void * - Addr nxm_tid; //!< scheduler's thread id - int64_t nxm_va; //!< page fault address - // struct nxm_pth_state * - Addr nxm_pthid; //!< id of null thread - uint64_t nxm_bound_pcs_count; //!< bound PCS thread count - int64_t pad[2]; //!< pad - }; - - /// nxm_shared. - struct nxm_shared { - int64_t nxm_callback; //!< address of upcall routine - unsigned int nxm_version; //!< version number - unsigned short nxm_uniq_offset; //!< correction factor for TEB - unsigned short pad1; //!< pad1 - int64_t space[2]; //!< future growth - struct nxm_sched_state nxm_ss[1]; //!< array of shared areas - }; - - /// nxm_slot_state_t. - enum nxm_slot_state_t { - NXM_SLOT_AVAIL, - NXM_SLOT_BOUND, - NXM_SLOT_UNBOUND, - NXM_SLOT_EMPTY - }; - - /// nxm_config_info - struct nxm_config_info { - int nxm_nslots_per_rad; //!< max number of VP slots per RAD - int nxm_nrads; //!< max number of RADs - // nxm_slot_state_t * - Addr nxm_slot_state; //!< per-VP slot state - // struct nxm_shared * - Addr nxm_rad[1]; //!< per-RAD shared areas - }; - - /// For nxm_thread_create. - enum nxm_thread_type { - NXM_TYPE_SCS = 0, - NXM_TYPE_VP = 1, - NXM_TYPE_MANAGER = 2 - }; - - /// Thread attributes. - struct nxm_thread_attr { - int version; //!< version - int type; //!< type - int cancel_flags; //!< cancel_flags - int priority; //!< priority - int policy; //!< policy - int signal_type; //!< signal_type - // void * - Addr pthid; //!< pthid - sigset_t sigmask; //!< sigmask - /// Initial register values. - struct { - uint64_t pc; //!< pc - uint64_t sp; //!< sp - uint64_t a0; //!< a0 - } registers; - uint64_t pad2[2]; //!< pad2 - }; - - /// Helper function to convert a host stat buffer to a target stat - /// buffer. Also copies the target buffer out to the simulated - /// memory space. Used by stat(), fstat(), and lstat(). - template <class T> - static void - copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host) - { - TypedBufferArg<T> tgt(addr); - - tgt->st_dev = htog(host->st_dev); - tgt->st_ino = htog(host->st_ino); - tgt->st_mode = htog(host->st_mode); - tgt->st_nlink = htog(host->st_nlink); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_atimeX = htog(host->st_atime); - tgt->st_mtimeX = htog(host->st_mtime); - tgt->st_ctimeX = htog(host->st_ctime); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_blocks = htog(host->st_blocks); - - tgt.copyOut(mem); - } - - /// Helper function to convert a host statfs buffer to a target statfs - /// buffer. Also copies the target buffer out to the simulated - /// memory space. Used by statfs() and fstatfs(). - template <class T> - static void - copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host) - { - TypedBufferArg<T> tgt(addr); - -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__) - tgt->f_type = 0; -#else - tgt->f_type = htog(host->f_type); -#endif - tgt->f_bsize = htog(host->f_bsize); - tgt->f_blocks = htog(host->f_blocks); - tgt->f_bfree = htog(host->f_bfree); - tgt->f_bavail = htog(host->f_bavail); - tgt->f_files = htog(host->f_files); - tgt->f_ffree = htog(host->f_ffree); - - // Is this as string normally? - memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid)); - - tgt.copyOut(mem); - } - - class F64 { - public: - static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, - global_stat *host) - { - Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host); - } - - static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, - global_statfs *host) - { - Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host); - } - }; - - class PreF64 { - public: - static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, - global_stat *host) - { - Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host); - } - - static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, - global_statfs *host) - { - Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host); - } - }; - - /// Helper function to convert a host stat buffer to an old pre-F64 - /// (4.x) target stat buffer. Also copies the target buffer out to - /// the simulated memory space. Used by pre_F64_stat(), - /// pre_F64_fstat(), and pre_F64_lstat(). - static void - copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host) - { - TypedBufferArg<Tru64::pre_F64_stat> tgt(addr); - - tgt->st_dev = htog(host->st_dev); - tgt->st_ino = htog(host->st_ino); - tgt->st_mode = htog(host->st_mode); - tgt->st_nlink = htog(host->st_nlink); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_atimeX = htog(host->st_atime); - tgt->st_mtimeX = htog(host->st_mtime); - tgt->st_ctimeX = htog(host->st_ctime); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_blocks = htog(host->st_blocks); - - tgt.copyOut(mem); - } - - - /// The target system's hostname. - static const char *hostname; - - /// Target uname() handler. - static SyscallReturn - unameFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0)); - - strcpy(name->sysname, "OSF1"); - strcpy(name->nodename, hostname); - strcpy(name->release, "V5.1"); - strcpy(name->version, "732"); - strcpy(name->machine, "alpha"); - - name.copyOut(xc->mem); - return 0; - } - - - /// Target getsysyinfo() handler. - static SyscallReturn - getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - unsigned op = xc->getSyscallArg(0); - unsigned nbytes = xc->getSyscallArg(2); - - switch (op) { - - case Tru64::GSI_MAX_CPU: { - TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1)); - *max_cpu = htog((uint32_t)process->numCpus()); - max_cpu.copyOut(xc->mem); - return 1; - } - - case Tru64::GSI_CPUS_IN_BOX: { - TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1)); - *cpus_in_box = htog((uint32_t)process->numCpus()); - cpus_in_box.copyOut(xc->mem); - return 1; - } - - case Tru64::GSI_PHYSMEM: { - TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1)); - *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB - physmem.copyOut(xc->mem); - return 1; - } - - case Tru64::GSI_CPU_INFO: { - TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1)); - - infop->current_cpu = htog(0); - infop->cpus_in_box = htog(process->numCpus()); - infop->cpu_type = htog(57); - infop->ncpus = htog(process->numCpus()); - uint64_t cpumask = (1 << process->numCpus()) - 1; - infop->cpus_present = infop->cpus_running = htog(cpumask); - infop->cpu_binding = htog(0); - infop->cpu_ex_binding = htog(0); - infop->mhz = htog(667); - - infop.copyOut(xc->mem); - return 1; - } - - case Tru64::GSI_PROC_TYPE: { - TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1)); - *proc_type = htog((uint64_t)11); - proc_type.copyOut(xc->mem); - return 1; - } - - case Tru64::GSI_PLATFORM_NAME: { - BufferArg bufArg(xc->getSyscallArg(1), nbytes); - strncpy((char *)bufArg.bufferPtr(), - "COMPAQ Professional Workstation XP1000", - nbytes); - bufArg.copyOut(xc->mem); - return 1; - } - - case Tru64::GSI_CLK_TCK: { - TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1)); - *clk_hz = htog((uint64_t)1024); - clk_hz.copyOut(xc->mem); - return 1; - } - - default: - warn("getsysinfo: unknown op %d\n", op); - break; - } - - return 0; - } - - /// Target setsysyinfo() handler. - static SyscallReturn - setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - unsigned op = xc->getSyscallArg(0); - - switch (op) { - case SSI_IEEE_FP_CONTROL: - warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", - xc->getSyscallArg(1)); - break; - - default: - warn("setsysinfo: unknown op %d\n", op); - break; - } - - return 0; - } - - /// Target fnctl() handler. - static SyscallReturn - fcntlFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - int fd = xc->getSyscallArg(0); - - if (fd < 0 || process->sim_fd(fd) < 0) - return -EBADF; - - int cmd = xc->getSyscallArg(1); - switch (cmd) { - case 0: // F_DUPFD - // if we really wanted to support this, we'd need to do it - // in the target fd space. - warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); - return -EMFILE; - - case 1: // F_GETFD (get close-on-exec flag) - case 2: // F_SETFD (set close-on-exec flag) - return 0; - - case 3: // F_GETFL (get file flags) - case 4: // F_SETFL (set file flags) - // not sure if this is totally valid, but we'll pass it through - // to the underlying OS - warn("fcntl(%d, %d) passed through to host\n", fd, cmd); - return fcntl(process->sim_fd(fd), cmd); - // return 0; - - case 7: // F_GETLK (get lock) - case 8: // F_SETLK (set lock) - case 9: // F_SETLKW (set lock and wait) - // don't mess with file locking... just act like it's OK - warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); - return 0; - - default: - warn("Unknown fcntl command %d\n", cmd); - return 0; - } - } - - - /// Target getdirentries() handler. - static SyscallReturn - getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { -#ifdef __CYGWIN__ - panic("getdirent not implemented on cygwin!"); -#else - int fd = process->sim_fd(xc->getSyscallArg(0)); - Addr tgt_buf = xc->getSyscallArg(1); - int tgt_nbytes = xc->getSyscallArg(2); - Addr tgt_basep = xc->getSyscallArg(3); - - char * const host_buf = new char[tgt_nbytes]; - - // just pass basep through uninterpreted. - TypedBufferArg<int64_t> basep(tgt_basep); - basep.copyIn(xc->mem); - long host_basep = (off_t)htog((int64_t)*basep); - int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep); - - // check for error - if (host_result < 0) { - delete [] host_buf; - return -errno; - } - - // no error: copy results back to target space - Addr tgt_buf_ptr = tgt_buf; - char *host_buf_ptr = host_buf; - char *host_buf_end = host_buf + host_result; - while (host_buf_ptr < host_buf_end) { - global_dirent *host_dp = (global_dirent *)host_buf_ptr; - int namelen = strlen(host_dp->d_name); - - // Actual size includes padded string rounded up for alignment. - // Subtract 256 for dummy char array in Tru64::dirent definition. - // Add 1 to namelen for terminating null char. - int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8); - TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize); - tgt_dp->d_ino = host_dp->d_ino; - tgt_dp->d_reclen = tgt_bufsize; - tgt_dp->d_namlen = namelen; - strcpy(tgt_dp->d_name, host_dp->d_name); - tgt_dp.copyOut(xc->mem); - - tgt_buf_ptr += tgt_bufsize; - host_buf_ptr += host_dp->d_reclen; - } - - delete [] host_buf; - - *basep = htog((int64_t)host_basep); - basep.copyOut(xc->mem); - - return tgt_buf_ptr - tgt_buf; -#endif - } - - /// Target sigreturn() handler. - static SyscallReturn - sigreturnFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - RegFile *regs = &xc->regs; - TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0)); - - sc.copyIn(xc->mem); - - // Restore state from sigcontext structure. - // Note that we'll advance PC <- NPC before the end of the cycle, - // so we need to restore the desired PC into NPC. - // The current regs->pc will get clobbered. - regs->npc = htog(sc->sc_pc); - - for (int i = 0; i < 31; ++i) { - regs->intRegFile[i] = htog(sc->sc_regs[i]); - regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]); - } - - regs->miscRegs.fpcr = htog(sc->sc_fpcr); - - return 0; - } - - /// Target table() handler. - static SyscallReturn - tableFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - int id = xc->getSyscallArg(0); // table ID - int index = xc->getSyscallArg(1); // index into table - // arg 2 is buffer pointer; type depends on table ID - int nel = xc->getSyscallArg(3); // number of elements - int lel = xc->getSyscallArg(4); // expected element size - - switch (id) { - case Tru64::TBL_SYSINFO: { - if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) - return -EINVAL; - TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2)); - - const int clk_hz = one_million; - elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); - elp->si_nice = htog(0); - elp->si_sys = htog(0); - elp->si_idle = htog(0); - elp->wait = htog(0); - elp->si_hz = htog(clk_hz); - elp->si_phz = htog(clk_hz); - elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? - elp->si_max_procs = htog(process->numCpus()); - elp.copyOut(xc->mem); - return 0; - } - - default: - cerr << "table(): id " << id << " unknown." << endl; - return -EINVAL; - } - } - - /// Array of syscall descriptors, indexed by call number. - static SyscallDesc syscallDescs[]; - - /// Number of syscalls in syscallDescs[]. - static const int Num_Syscall_Descs; - - /// Max supported syscall number. - static const int Max_Syscall_Desc; - - // - // Mach syscalls -- identified by negated syscall numbers - // - - /// Create a stack region for a thread. - static SyscallReturn - stack_createFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0)); - - argp.copyIn(xc->mem); - - // if the user chose an address, just let them have it. Otherwise - // pick one for them. - if (htog(argp->address) == 0) { - argp->address = htog(process->next_thread_stack_base); - int stack_size = (htog(argp->rsize) + htog(argp->ysize) + - htog(argp->gsize)); - process->next_thread_stack_base -= stack_size; - argp.copyOut(xc->mem); - } - - return 0; - } - - /// NXM library version stamp. - static - const int NXM_LIB_VERSION = 301003; - - /// This call sets up the interface between the user and kernel - /// schedulers by creating a shared-memory region. The shared memory - /// region has several structs, some global, some per-RAD, some per-VP. - static SyscallReturn - nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0)); - TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1)); - - attrp.copyIn(xc->mem); - - if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) { - cerr << "nxm_task_init: thread library version mismatch! " - << "got " << attrp->nxm_version - << ", expected " << NXM_LIB_VERSION << endl; - abort(); - } - - if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) { - cerr << "nxm_task_init: bad flag value " << attrp->flags - << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl; - abort(); - } - - const Addr base_addr = 0x12000; // was 0x3f0000000LL; - Addr cur_addr = base_addr; // next addresses to use - // first comes the config_info struct - Addr config_addr = cur_addr; - cur_addr += sizeof(Tru64::nxm_config_info); - // next comes the per-cpu state vector - Addr slot_state_addr = cur_addr; - int slot_state_size = - process->numCpus() * sizeof(Tru64::nxm_slot_state_t); - cur_addr += slot_state_size; - // now the per-RAD state struct (we only support one RAD) - cur_addr = 0x14000; // bump up addr for alignment - Addr rad_state_addr = cur_addr; - int rad_state_size = - (sizeof(Tru64::nxm_shared) - + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state)); - cur_addr += rad_state_size; - - // now initialize a config_info struct and copy it out to user space - TypedBufferArg<Tru64::nxm_config_info> config(config_addr); - - config->nxm_nslots_per_rad = htog(process->numCpus()); - config->nxm_nrads = htog(1); // only one RAD in our system! - config->nxm_slot_state = htog(slot_state_addr); - config->nxm_rad[0] = htog(rad_state_addr); - - config.copyOut(xc->mem); - - // initialize the slot_state array and copy it out - TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr, - slot_state_size); - for (int i = 0; i < process->numCpus(); ++i) { - // CPU 0 is bound to the calling process; all others are available - // XXX this code should have an endian conversion, but I don't think - // it works anyway - slot_state[i] = - (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL; - } - - slot_state.copyOut(xc->mem); - - // same for the per-RAD "shared" struct. Note that we need to - // allocate extra bytes for the per-VP array which is embedded at - // the end. - TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr, - rad_state_size); - - rad_state->nxm_callback = attrp->nxm_callback; - rad_state->nxm_version = attrp->nxm_version; - rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset; - for (int i = 0; i < process->numCpus(); ++i) { - Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i]; - ssp->nxm_u.sigmask = htog(0); - ssp->nxm_u.sig = htog(0); - ssp->nxm_u.flags = htog(0); - ssp->nxm_u.cancel_state = htog(0); - ssp->nxm_u.nxm_ssig = 0; - ssp->nxm_bits = htog(0); - ssp->nxm_quantum = attrp->nxm_quantum; - ssp->nxm_set_quantum = attrp->nxm_quantum; - ssp->nxm_sysevent = htog(0); - - if (i == 0) { - uint64_t uniq = xc->regs.miscRegs.uniq; - ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset)); - ssp->nxm_u.nxm_active = htog(uniq | 1); - } - else { - ssp->nxm_u.pth_id = htog(0); - ssp->nxm_u.nxm_active = htog(0); - } - } - - rad_state.copyOut(xc->mem); - - // - // copy pointer to shared config area out to user - // - *configptr_ptr = htog(config_addr); - configptr_ptr.copyOut(xc->mem); - - // Register this as a valid address range with the process - process->nxm_start = base_addr; - process->nxm_end = cur_addr; - - return 0; - } - - /// Initialize execution context. - static void - init_exec_context(ExecContext *ec, - Tru64::nxm_thread_attr *attrp, uint64_t uniq_val) - { - memset(&ec->regs, 0, sizeof(ec->regs)); - - ec->regs.intRegFile[ArgumentReg0] = gtoh(attrp->registers.a0); - ec->regs.intRegFile[27/*t12*/] = gtoh(attrp->registers.pc); - ec->regs.intRegFile[StackPointerReg] = gtoh(attrp->registers.sp); - ec->regs.miscRegs.uniq = uniq_val; - - ec->regs.pc = gtoh(attrp->registers.pc); - ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(MachInst); - - ec->activate(); - } - - /// Create thread. - static SyscallReturn - nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0)); - TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1)); - int thread_index = xc->getSyscallArg(2); - - // get attribute args - attrp.copyIn(xc->mem); - - if (gtoh(attrp->version) != NXM_LIB_VERSION) { - cerr << "nxm_thread_create: thread library version mismatch! " - << "got " << attrp->version - << ", expected " << NXM_LIB_VERSION << endl; - abort(); - } - - if (thread_index < 0 | thread_index > process->numCpus()) { - cerr << "nxm_thread_create: bad thread index " << thread_index - << endl; - abort(); - } - - // On a real machine, the per-RAD shared structure is in - // shared memory, so both the user and kernel can get at it. - // We don't have that luxury, so we just copy it in and then - // back out again. - int rad_state_size = - (sizeof(Tru64::nxm_shared) + - (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state)); - - TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000, - rad_state_size); - rad_state.copyIn(xc->mem); - - uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset); - - if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) { - // DEC pthreads seems to always create one of these (in - // addition to N application threads), but we don't use it, - // so don't bother creating it. - - // This is supposed to be a port number. Make something up. - *kidp = htog(99); - kidp.copyOut(xc->mem); - - return 0; - } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) { - // A real "virtual processor" kernel thread. Need to fork - // this thread on another CPU. - Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index]; - - if (gtoh(ssp->nxm_u.nxm_active) != 0) - return (int) Tru64::KERN_NOT_RECEIVER; - - ssp->nxm_u.pth_id = attrp->pthid; - ssp->nxm_u.nxm_active = htog(uniq_val | 1); - - rad_state.copyOut(xc->mem); - - Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info); - int slot_state_size = - process->numCpus() * sizeof(Tru64::nxm_slot_state_t); - - TypedBufferArg<Tru64::nxm_slot_state_t> - slot_state(slot_state_addr, - slot_state_size); - - slot_state.copyIn(xc->mem); - - if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) { - cerr << "nxm_thread_createFunc: requested VP slot " - << thread_index << " not available!" << endl; - fatal(""); - } - - // XXX This should have an endian conversion but I think this code - // doesn't work anyway - slot_state[thread_index] = Tru64::NXM_SLOT_BOUND; - - slot_state.copyOut(xc->mem); - - // Find a free simulator execution context. - for (int i = 0; i < process->numCpus(); ++i) { - ExecContext *xc = process->execContexts[i]; - - if (xc->status() == ExecContext::Unallocated) { - // inactive context... grab it - init_exec_context(xc, attrp, uniq_val); - - // This is supposed to be a port number, but we'll try - // and get away with just sticking the thread index - // here. - *kidp = htog(thread_index); - kidp.copyOut(xc->mem); - - return 0; - } - } - - // fell out of loop... no available inactive context - cerr << "nxm_thread_create: no idle contexts available." << endl; - abort(); - } else { - cerr << "nxm_thread_create: can't handle thread type " - << attrp->type << endl; - abort(); - } - - return 0; - } - - /// Thread idle call (like yield()). - static SyscallReturn - nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - return 0; - } - - /// Block thread. - static SyscallReturn - nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - uint64_t tid = xc->getSyscallArg(0); - uint64_t secs = xc->getSyscallArg(1); - uint64_t flags = xc->getSyscallArg(2); - uint64_t action = xc->getSyscallArg(3); - uint64_t usecs = xc->getSyscallArg(4); - - cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs - << " " << flags << " " << action << " " << usecs << endl; - - return 0; - } - - /// block. - static SyscallReturn - nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr uaddr = xc->getSyscallArg(0); - uint64_t val = xc->getSyscallArg(1); - uint64_t secs = xc->getSyscallArg(2); - uint64_t usecs = xc->getSyscallArg(3); - uint64_t flags = xc->getSyscallArg(4); - - BaseCPU *cpu = xc->cpu; - - cout << cpu->name() << ": nxm_block " - << hex << uaddr << dec << " " << val - << " " << secs << " " << usecs - << " " << flags << endl; - - return 0; - } - - /// Unblock thread. - static SyscallReturn - nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr uaddr = xc->getSyscallArg(0); - - cout << xc->cpu->name() << ": nxm_unblock " - << hex << uaddr << dec << endl; - - return 0; - } - - /// Switch thread priority. - static SyscallReturn - swtch_priFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - // Attempts to switch to another runnable thread (if there is - // one). Returns false if there are no other threads to run - // (i.e., the thread can reasonably spin-wait) or true if there - // are other threads. - // - // Since we assume at most one "kernel" thread per CPU, it's - // always safe to return false here. - return 0; //false; - } - - - /// Activate exec context waiting on a channel. Just activate one - /// by default. - static int - activate_waiting_context(Addr uaddr, Process *process, - bool activate_all = false) - { - int num_activated = 0; - - list<Process::WaitRec>::iterator i = process->waitList.begin(); - list<Process::WaitRec>::iterator end = process->waitList.end(); - - while (i != end && (num_activated == 0 || activate_all)) { - if (i->waitChan == uaddr) { - // found waiting process: make it active - ExecContext *newCtx = i->waitingContext; - assert(newCtx->status() == ExecContext::Suspended); - newCtx->activate(); - - // get rid of this record - i = process->waitList.erase(i); - - ++num_activated; - } else { - ++i; - } - } - - return num_activated; - } - - /// M5 hacked-up lock acquire. - static void - m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc) - { - TypedBufferArg<uint64_t> lockp(uaddr); - - lockp.copyIn(xc->mem); - - if (gtoh(*lockp) == 0) { - // lock is free: grab it - *lockp = htog(1); - lockp.copyOut(xc->mem); - } else { - // lock is busy: disable until free - process->waitList.push_back(Process::WaitRec(uaddr, xc)); - xc->suspend(); - } - } - - /// M5 unlock call. - static void - m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc) - { - TypedBufferArg<uint64_t> lockp(uaddr); - - lockp.copyIn(xc->mem); - assert(*lockp != 0); - - // Check for a process waiting on the lock. - int num_waiting = activate_waiting_context(uaddr, process); - - // clear lock field if no waiting context is taking over the lock - if (num_waiting == 0) { - *lockp = 0; - lockp.copyOut(xc->mem); - } - } - - /// Lock acquire syscall handler. - static SyscallReturn - m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr uaddr = xc->getSyscallArg(0); - - m5_lock_mutex(uaddr, process, xc); - - // Return 0 since we will always return to the user with the lock - // acquired. We will just keep the context inactive until that is - // true. - return 0; - } - - /// Try lock (non-blocking). - static SyscallReturn - m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr uaddr = xc->getSyscallArg(0); - TypedBufferArg<uint64_t> lockp(uaddr); - - lockp.copyIn(xc->mem); - - if (gtoh(*lockp) == 0) { - // lock is free: grab it - *lockp = htog(1); - lockp.copyOut(xc->mem); - return 0; - } else { - return 1; - } - } - - /// Unlock syscall handler. - static SyscallReturn - m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr uaddr = xc->getSyscallArg(0); - - m5_unlock_mutex(uaddr, process, xc); - - return 0; - } - - /// Signal ocndition. - static SyscallReturn - m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr cond_addr = xc->getSyscallArg(0); - - // Wake up one process waiting on the condition variable. - activate_waiting_context(cond_addr, process); - - return 0; - } - - /// Wake up all processes waiting on the condition variable. - static SyscallReturn - m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr cond_addr = xc->getSyscallArg(0); - - activate_waiting_context(cond_addr, process, true); - - return 0; - } - - /// Wait on a condition. - static SyscallReturn - m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - Addr cond_addr = xc->getSyscallArg(0); - Addr lock_addr = xc->getSyscallArg(1); - TypedBufferArg<uint64_t> condp(cond_addr); - TypedBufferArg<uint64_t> lockp(lock_addr); - - // user is supposed to acquire lock before entering - lockp.copyIn(xc->mem); - assert(gtoh(*lockp) != 0); - - m5_unlock_mutex(lock_addr, process, xc); - - process->waitList.push_back(Process::WaitRec(cond_addr, xc)); - xc->suspend(); - - return 0; - } - - /// Thread exit. - static SyscallReturn - m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - assert(xc->status() == ExecContext::Active); - xc->deallocate(); - - return 0; - } - - /// Array of syscall descriptors for Mach syscalls, indexed by - /// (negated) call number. - static SyscallDesc machSyscallDescs[]; - - /// Number of syscalls in machSyscallDescs[]. - static const int Num_Mach_Syscall_Descs; - - /// Max supported Mach syscall number. - static const int Max_Mach_Syscall_Desc; - - /// Since negated values are used to identify Mach syscalls, the - /// minimum (signed) valid syscall number is the negated max Mach - /// syscall number. - static const int Min_Syscall_Desc; +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0)); - /// Do the specified syscall. Just looks the call number up in - /// the table and invokes the appropriate handler. - static void - doSyscall(int callnum, Process *process, ExecContext *xc) - { - if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) { - fatal("Syscall %d out of range\n", callnum); - } + strcpy(name->sysname, "OSF1"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "V5.1"); + strcpy(name->version, "732"); + strcpy(name->machine, "alpha"); - SyscallDesc *desc = - (callnum < 0) ? - &machSyscallDescs[-callnum] : &syscallDescs[callnum]; + name.copyOut(xc->mem); + return 0; +} - desc->doSyscall(callnum, process, xc); +/// Target getsysyinfo() handler. +static SyscallReturn +getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case Tru64::GSI_MAX_CPU: { + TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1)); + *max_cpu = htog((uint32_t)process->numCpus()); + max_cpu.copyOut(xc->mem); + return 1; + } + + case Tru64::GSI_CPUS_IN_BOX: { + TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1)); + *cpus_in_box = htog((uint32_t)process->numCpus()); + cpus_in_box.copyOut(xc->mem); + return 1; + } + + case Tru64::GSI_PHYSMEM: { + TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1)); + *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB + physmem.copyOut(xc->mem); + return 1; + } + + case Tru64::GSI_CPU_INFO: { + TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1)); + + infop->current_cpu = htog(0); + infop->cpus_in_box = htog(process->numCpus()); + infop->cpu_type = htog(57); + infop->ncpus = htog(process->numCpus()); + uint64_t cpumask = (1 << process->numCpus()) - 1; + infop->cpus_present = infop->cpus_running = htog(cpumask); + infop->cpu_binding = htog(0); + infop->cpu_ex_binding = htog(0); + infop->mhz = htog(667); + + infop.copyOut(xc->mem); + return 1; + } + + case Tru64::GSI_PROC_TYPE: { + TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1)); + *proc_type = htog((uint64_t)11); + proc_type.copyOut(xc->mem); + return 1; + } + + case Tru64::GSI_PLATFORM_NAME: { + BufferArg bufArg(xc->getSyscallArg(1), nbytes); + strncpy((char *)bufArg.bufferPtr(), + "COMPAQ Professional Workstation XP1000", + nbytes); + bufArg.copyOut(xc->mem); + return 1; + } + + case Tru64::GSI_CLK_TCK: { + TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1)); + *clk_hz = htog((uint64_t)1024); + clk_hz.copyOut(xc->mem); + return 1; + } + + default: + warn("getsysinfo: unknown op %d\n", op); + break; } - /// Indirect syscall invocation (call #0). - static SyscallReturn - indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - int new_callnum = xc->getSyscallArg(0); + return 0; +} - for (int i = 0; i < 5; ++i) - xc->setSyscallArg(i, xc->getSyscallArg(i+1)); +/// Target setsysyinfo() handler. +static SyscallReturn +setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); - doSyscall(new_callnum, process, xc); + switch (op) { + case Tru64::SSI_IEEE_FP_CONTROL: + warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", + xc->getSyscallArg(1)); + break; - return 0; + default: + warn("setsysinfo: unknown op %d\n", op); + break; } -}; // class Tru64 - - -// open(2) flags translation table -OpenFlagTransTable Tru64::openFlagTable[] = { -#ifdef _MSC_VER - { Tru64::TGT_O_RDONLY, _O_RDONLY }, - { Tru64::TGT_O_WRONLY, _O_WRONLY }, - { Tru64::TGT_O_RDWR, _O_RDWR }, - { Tru64::TGT_O_APPEND, _O_APPEND }, - { Tru64::TGT_O_CREAT, _O_CREAT }, - { Tru64::TGT_O_TRUNC, _O_TRUNC }, - { Tru64::TGT_O_EXCL, _O_EXCL }, -#ifdef _O_NONBLOCK - { Tru64::TGT_O_NONBLOCK, _O_NONBLOCK }, -#endif -#ifdef _O_NOCTTY - { Tru64::TGT_O_NOCTTY, _O_NOCTTY }, -#endif -#ifdef _O_SYNC - { Tru64::TGT_O_SYNC, _O_SYNC }, -#endif -#else /* !_MSC_VER */ - { Tru64::TGT_O_RDONLY, O_RDONLY }, - { Tru64::TGT_O_WRONLY, O_WRONLY }, - { Tru64::TGT_O_RDWR, O_RDWR }, - { Tru64::TGT_O_APPEND, O_APPEND }, - { Tru64::TGT_O_CREAT, O_CREAT }, - { Tru64::TGT_O_TRUNC, O_TRUNC }, - { Tru64::TGT_O_EXCL, O_EXCL }, - { Tru64::TGT_O_NONBLOCK, O_NONBLOCK }, - { Tru64::TGT_O_NOCTTY, O_NOCTTY }, -#ifdef O_SYNC - { Tru64::TGT_O_SYNC, O_SYNC }, -#endif -#endif /* _MSC_VER */ -}; - -const int Tru64::NUM_OPEN_FLAGS = (sizeof(Tru64::openFlagTable)/sizeof(Tru64::openFlagTable[0])); + return 0; +} -const char *Tru64::hostname = "m5.eecs.umich.edu"; -SyscallDesc Tru64::syscallDescs[] = { - /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc, +SyscallDesc AlphaTru64Process::syscallDescs[] = { + /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc, SyscallDesc::SuppressReturnValue), /* 1 */ SyscallDesc("exit", exitFunc), /* 2 */ SyscallDesc("fork", unimplementedFunc), @@ -1637,7 +244,7 @@ SyscallDesc Tru64::syscallDescs[] = { /* 82 */ SyscallDesc("setpgrp", unimplementedFunc), /* 83 */ SyscallDesc("setitimer", unimplementedFunc), /* 84 */ SyscallDesc("old_wait", unimplementedFunc), - /* 85 */ SyscallDesc("table", tableFunc), + /* 85 */ SyscallDesc("table", Tru64::tableFunc), /* 86 */ SyscallDesc("getitimer", unimplementedFunc), /* 87 */ SyscallDesc("gethostname", gethostnameFunc), /* 88 */ SyscallDesc("sethostname", unimplementedFunc), @@ -1655,7 +262,7 @@ SyscallDesc Tru64::syscallDescs[] = { /* 100 */ SyscallDesc("getpriority", unimplementedFunc), /* 101 */ SyscallDesc("old_send", unimplementedFunc), /* 102 */ SyscallDesc("old_recv", unimplementedFunc), - /* 103 */ SyscallDesc("sigreturn", sigreturnFunc, + /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc, SyscallDesc::SuppressReturnValue), /* 104 */ SyscallDesc("bind", unimplementedFunc), /* 105 */ SyscallDesc("setsockopt", unimplementedFunc), @@ -1712,7 +319,7 @@ SyscallDesc Tru64::syscallDescs[] = { /* 156 */ SyscallDesc("sigaction", ignoreFunc), /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc), /* 158 */ SyscallDesc("nfssvc", unimplementedFunc), - /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc), + /* 159 */ SyscallDesc("getdirentries", Tru64::getdirentriesFunc), /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>), /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>), /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), @@ -1822,20 +429,17 @@ SyscallDesc Tru64::syscallDescs[] = { /* 266 */ SyscallDesc("sendfile", unimplementedFunc), }; -const int Tru64::Num_Syscall_Descs = - sizeof(Tru64::syscallDescs) / sizeof(SyscallDesc); -const int Tru64::Max_Syscall_Desc = Tru64::Num_Syscall_Descs - 1; -SyscallDesc Tru64::machSyscallDescs[] = { +SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 1 */ SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc), - /* 2 */ SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc), - /* 3 */ SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc), - /* 4 */ SyscallDesc("m5_cond_signal", m5_cond_signalFunc), - /* 5 */ SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc), - /* 6 */ SyscallDesc("m5_cond_wait", m5_cond_waitFunc), - /* 7 */ SyscallDesc("m5_thread_exit", m5_thread_exitFunc), + /* 1 */ SyscallDesc("m5_mutex_lock", Tru64::m5_mutex_lockFunc), + /* 2 */ SyscallDesc("m5_mutex_trylock", Tru64::m5_mutex_trylockFunc), + /* 3 */ SyscallDesc("m5_mutex_unlock", Tru64::m5_mutex_unlockFunc), + /* 4 */ SyscallDesc("m5_cond_signal", Tru64::m5_cond_signalFunc), + /* 5 */ SyscallDesc("m5_cond_broadcast", Tru64::m5_cond_broadcastFunc), + /* 6 */ SyscallDesc("m5_cond_wait", Tru64::m5_cond_waitFunc), + /* 7 */ SyscallDesc("m5_thread_exit", Tru64::m5_thread_exitFunc), /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 10 */ SyscallDesc("task_self", unimplementedFunc), @@ -1852,22 +456,22 @@ SyscallDesc Tru64::machSyscallDescs[] = { /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc), /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc), /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc), - /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc), + /* 24 */ SyscallDesc("nxm_block", Tru64::nxm_blockFunc), + /* 25 */ SyscallDesc("nxm_unblock", Tru64::nxm_unblockFunc), /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc), /* 30 */ SyscallDesc("lw_wire", unimplementedFunc), /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc), - /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc), - /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc), + /* 32 */ SyscallDesc("nxm_thread_create", Tru64::nxm_thread_createFunc), + /* 33 */ SyscallDesc("nxm_task_init", Tru64::nxm_task_initFunc), /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc), + /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc), /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc), /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc), /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc), - /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc), + /* 39 */ SyscallDesc("nxm_thread_block", Tru64::nxm_thread_blockFunc), /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc), /* 41 */ SyscallDesc("init_process", unimplementedFunc), /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc), @@ -1875,7 +479,7 @@ SyscallDesc Tru64::machSyscallDescs[] = { /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc), /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc), /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc), - /* 47 */ SyscallDesc("stack_create", stack_createFunc), + /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc), /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc), /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc), /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc), @@ -1887,7 +491,7 @@ SyscallDesc Tru64::machSyscallDescs[] = { /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc), /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc), + /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc), /* 60 */ SyscallDesc("swtch", unimplementedFunc), /* 61 */ SyscallDesc("thread_switch", unimplementedFunc), /* 62 */ SyscallDesc("semop_fast", unimplementedFunc), @@ -1895,7 +499,7 @@ SyscallDesc Tru64::machSyscallDescs[] = { /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc), /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc), /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc), - /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc), + /* 67 */ SyscallDesc("nxm_swtch_pri", Tru64::swtch_priFunc), /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc), /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc), @@ -1913,20 +517,16 @@ SyscallDesc Tru64::machSyscallDescs[] = { /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc) }; -const int Tru64::Num_Mach_Syscall_Descs = - sizeof(Tru64::machSyscallDescs) / sizeof(SyscallDesc); -const int Tru64::Max_Mach_Syscall_Desc = Tru64::Num_Mach_Syscall_Descs - 1; -const int Tru64::Min_Syscall_Desc = -Tru64::Max_Mach_Syscall_Desc; - - -void -AlphaTru64Process::syscall(ExecContext *xc) +SyscallDesc* +AlphaTru64Process::getDesc(int callnum) { - num_syscalls++; - - int64_t callnum = xc->regs.intRegFile[ReturnValueReg]; + if (callnum < -Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs) + return NULL; - Tru64::doSyscall(callnum, this, xc); + if (callnum < 0) + return &machSyscallDescs[-callnum]; + else + return &syscallDescs[callnum]; } @@ -1937,6 +537,8 @@ AlphaTru64Process::AlphaTru64Process(const std::string &name, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) - : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp) + : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)), + Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc)) { } diff --git a/arch/alpha/alpha_tru64_process.hh b/arch/alpha/alpha_tru64_process.hh index 49979806c..051760702 100644 --- a/arch/alpha/alpha_tru64_process.hh +++ b/arch/alpha/alpha_tru64_process.hh @@ -42,8 +42,16 @@ class AlphaTru64Process : public LiveProcess std::vector<std::string> &argv, std::vector<std::string> &envp); - /// Syscall emulation function. - virtual void syscall(ExecContext *xc); + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + /// Array of mach syscall descriptors, indexed by call number. + static SyscallDesc machSyscallDescs[]; + + const int Num_Syscall_Descs; + const int Num_Mach_Syscall_Descs; + + virtual SyscallDesc* getDesc(int callnum); }; diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc index a340a2053..4e8190cbc 100644 --- a/arch/alpha/arguments.cc +++ b/arch/alpha/arguments.cc @@ -31,6 +31,8 @@ #include "cpu/exec_context.hh" #include "mem/functional/physical.hh" +using namespace AlphaISA; + AlphaArguments::Data::~Data() { while (!data.empty()) { diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh index 5173b364f..7c8465cfb 100644 --- a/arch/alpha/ev5.hh +++ b/arch/alpha/ev5.hh @@ -30,9 +30,13 @@ #define __ARCH_ALPHA_EV5_HH__ #include "config/alpha_tlaser.hh" +#include "arch/alpha/isa_traits.hh" namespace EV5 { +//It seems like a safe assumption EV5 only applies to alpha +using namespace AlphaISA; + #if ALPHA_TLASER const uint64_t AsnMask = ULL(0x7f); #else diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc index 3aecf029d..fa4950198 100644 --- a/arch/alpha/faults.cc +++ b/arch/alpha/faults.cc @@ -28,34 +28,53 @@ #include "arch/alpha/faults.hh" -namespace { - const char * - fault_name[Num_Faults] = { - "none", - "reset", - "mchk", - "arith", - "interrupt", - "dtb_miss_single", - "dtb_miss_double", - "unalign", - "dfault", - "dfault", - "itbmiss", - "itbmiss", - "iaccvio", - "opdec", - "fen", - "pal", - }; -} +ResetFaultType * const ResetFault = + new ResetFaultType("reset", 1, 0x0001); +ArithmeticFaultType * const ArithmeticFault = + new ArithmeticFaultType("arith", 3, 0x0501); +InterruptFaultType * const InterruptFault = + new InterruptFaultType("interrupt", 4, 0x0101); +NDtbMissFaultType * const NDtbMissFault = + new NDtbMissFaultType("dtb_miss_single", 5, 0x0201); +PDtbMissFaultType * const PDtbMissFault = + new PDtbMissFaultType("dtb_miss_double", 6, 0x0281); +DtbPageFaultType * const DtbPageFault = + new DtbPageFaultType("dfault", 8, 0x0381); +DtbAcvFaultType * const DtbAcvFault = + new DtbAcvFaultType("dfault", 9, 0x0381); +ItbMissFaultType * const ItbMissFault = + new ItbMissFaultType("itbmiss", 10, 0x0181); +ItbPageFaultType * const ItbPageFault = + new ItbPageFaultType("itbmiss", 11, 0x0181); +ItbAcvFaultType * const ItbAcvFault = + new ItbAcvFaultType("iaccvio", 12, 0x0081); +UnimplementedOpcodeFaultType * const UnimplementedOpcodeFault = + new UnimplementedOpcodeFaultType("opdec", 13, 0x0481); +FloatEnableFaultType * const FloatEnableFault = + new FloatEnableFaultType("fen", 14, 0x0581); +PalFaultType * const PalFault = + new PalFaultType("pal", 15, 0x2001); +IntegerOverflowFaultType * const IntegerOverflowFault = + new IntegerOverflowFaultType("intover", 16, 0x0501); -const char * -FaultName(int index) -{ - if (index < 0 || index >= Num_Faults) - return 0; - - return fault_name[index]; -} +Fault * ListOfFaults[] = { + (Fault *)&NoFault, + (Fault *)&ResetFault, + (Fault *)&MachineCheckFault, + (Fault *)&ArithmeticFault, + (Fault *)&InterruptFault, + (Fault *)&NDtbMissFault, + (Fault *)&PDtbMissFault, + (Fault *)&AlignmentFault, + (Fault *)&DtbPageFault, + (Fault *)&DtbAcvFault, + (Fault *)&ItbMissFault, + (Fault *)&ItbPageFault, + (Fault *)&ItbAcvFault, + (Fault *)&UnimplementedOpcodeFault, + (Fault *)&FloatEnableFault, + (Fault *)&PalFault, + (Fault *)&IntegerOverflowFault, + }; +int NumFaults = sizeof(ListOfFaults) / sizeof(Fault *); diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh index bbac7cbf2..3e25adc4e 100644 --- a/arch/alpha/faults.hh +++ b/arch/alpha/faults.hh @@ -26,32 +26,135 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __FAULTS_HH__ -#define __FAULTS_HH__ - -enum Fault { - No_Fault, - Reset_Fault, // processor reset - Machine_Check_Fault, // machine check (also internal S/W fault) - Arithmetic_Fault, // FP exception - Interrupt_Fault, // external interrupt - Ndtb_Miss_Fault, // DTB miss - Pdtb_Miss_Fault, // nested DTB miss - Alignment_Fault, // unaligned access - DTB_Fault_Fault, // DTB page fault - DTB_Acv_Fault, // DTB access violation - ITB_Miss_Fault, // ITB miss - ITB_Fault_Fault, // ITB page fault - ITB_Acv_Fault, // ITB access violation - Unimplemented_Opcode_Fault, // invalid/unimplemented instruction - Fen_Fault, // FP not-enabled fault - Pal_Fault, // call_pal S/W interrupt - Integer_Overflow_Fault, - Fake_Mem_Fault, - Num_Faults // number of faults +#ifndef __ALPHA_FAULTS_HH__ +#define __ALPHA_FAULTS_HH__ + +#include "sim/faults.hh" +#include "arch/isa_traits.hh" //For the Addr type + +class AlphaFault : public FaultBase +{ + public: + AlphaFault(char * newName, int newId, Addr newVect) + : FaultBase(newName, newId), vect(newVect) + {;} + + Addr vect; }; -const char * -FaultName(int index); +extern class ResetFaultType : public AlphaFault +{ + public: + ResetFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const ResetFault; + +extern class ArithmeticFaultType : public AlphaFault +{ + public: + ArithmeticFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const ArithmeticFault; + +extern class InterruptFaultType : public AlphaFault +{ + public: + InterruptFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const InterruptFault; + +extern class NDtbMissFaultType : public AlphaFault +{ + public: + NDtbMissFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const NDtbMissFault; + +extern class PDtbMissFaultType : public AlphaFault +{ + public: + PDtbMissFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const PDtbMissFault; + +extern class DtbPageFaultType : public AlphaFault +{ + public: + DtbPageFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const DtbPageFault; + +extern class DtbAcvFaultType : public AlphaFault +{ + public: + DtbAcvFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const DtbAcvFault; + +extern class ItbMissFaultType : public AlphaFault +{ + public: + ItbMissFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const ItbMissFault; + +extern class ItbPageFaultType : public AlphaFault +{ + public: + ItbPageFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const ItbPageFault; + +extern class ItbAcvFaultType : public AlphaFault +{ + public: + ItbAcvFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const ItbAcvFault; + +extern class UnimplementedOpcodeFaultType : public AlphaFault +{ + public: + UnimplementedOpcodeFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const UnimplementedOpcodeFault; + +extern class FloatEnableFaultType : public AlphaFault +{ + public: + FloatEnableFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const FloatEnableFault; + +extern class PalFaultType : public AlphaFault +{ + public: + PalFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const PalFault; + +extern class IntegerOverflowFaultType : public AlphaFault +{ + public: + IntegerOverflowFaultType(char * newName, int newId, Addr newVect) + : AlphaFault(newName, newId, newVect) + {;} +} * const IntegerOverflowFault; + +extern Fault * ListOfFaults[]; +extern int NumFaults; #endif // __FAULTS_HH__ diff --git a/arch/alpha/isa/branch.isa b/arch/alpha/isa/branch.isa index e9c790c53..9a7fb9d79 100644 --- a/arch/alpha/isa/branch.isa +++ b/arch/alpha/isa/branch.isa @@ -205,8 +205,8 @@ output decoder {{ def template JumpOrBranchDecode {{ return (RA == 31) - ? (StaticInst<AlphaISA> *)new %(class_name)s(machInst) - : (StaticInst<AlphaISA> *)new %(class_name)sAndLink(machInst); + ? (StaticInst *)new %(class_name)s(machInst) + : (StaticInst *)new %(class_name)sAndLink(machInst); }}; def format CondBranch(code) {{ diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa index aff8571e9..37b15416b 100644 --- a/arch/alpha/isa/decoder.isa +++ b/arch/alpha/isa/decoder.isa @@ -98,7 +98,7 @@ decode OPCODE default Unknown::unknown() { // signed overflow occurs when operands have same sign // and sign of result does not match. if (Ra.sl<31:> == Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Rc.sl = tmp; }}); 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }}); @@ -110,7 +110,7 @@ decode OPCODE default Unknown::unknown() { // signed overflow occurs when operands have same sign // and sign of result does not match. if (Ra<63:> == Rb_or_imm<63:> && tmp<63:> != Ra<63:>) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Rc = tmp; }}); 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }}); @@ -124,7 +124,7 @@ decode OPCODE default Unknown::unknown() { // sign bit of the subtrahend (Rb), i.e., if the initial // signs are the *same* then no overflow can occur if (Ra.sl<31:> != Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Rc.sl = tmp; }}); 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }}); @@ -138,7 +138,7 @@ decode OPCODE default Unknown::unknown() { // sign bit of the subtrahend (Rb), i.e., if the initial // signs are the *same* then no overflow can occur if (Ra<63:> != Rb_or_imm<63:> && tmp<63:> != Ra<63:>) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Rc = tmp; }}); 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }}); @@ -299,7 +299,7 @@ decode OPCODE default Unknown::unknown() { // checking the upper 33 bits for all 0s or all 1s. uint64_t sign_bits = tmp<63:31>; if (sign_bits != 0 && sign_bits != mask(33)) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Rc.sl = tmp<31:0>; }}, IntMultOp); 0x60: mulqv({{ @@ -310,7 +310,7 @@ decode OPCODE default Unknown::unknown() { // the lower 64 if (!((hi == 0 && lo<63:> == 0) || (hi == mask(64) && lo<63:> == 1))) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Rc = lo; }}, IntMultOp); } @@ -427,19 +427,19 @@ decode OPCODE default Unknown::unknown() { #if SS_COMPATIBLE_FP 0x0b: sqrts({{ if (Fb < 0.0) - fault = Arithmetic_Fault; + fault = ArithmeticFault; Fc = sqrt(Fb); }}, FloatSqrtOp); #else 0x0b: sqrts({{ if (Fb.sf < 0.0) - fault = Arithmetic_Fault; + fault = ArithmeticFault; Fc.sf = sqrt(Fb.sf); }}, FloatSqrtOp); #endif 0x2b: sqrtt({{ if (Fb < 0.0) - fault = Arithmetic_Fault; + fault = ArithmeticFault; Fc = sqrt(Fb); }}, FloatSqrtOp); } @@ -570,7 +570,7 @@ decode OPCODE default Unknown::unknown() { // checking the upper 33 bits for all 0s or all 1s. uint64_t sign_bits = Fb.uq<63:31>; if (sign_bits != 0 && sign_bits != mask(33)) - fault = Integer_Overflow_Fault; + fault = IntegerOverflowFault; Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29); }}); @@ -673,7 +673,7 @@ decode OPCODE default Unknown::unknown() { && xc->readIpr(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) { // invalid pal function code, or attempt to do privileged // PAL call in non-kernel mode - fault = Unimplemented_Opcode_Fault; + fault = UnimplementedOpcodeFault; } else { // check to see if simulator wants to do something special @@ -729,7 +729,7 @@ decode OPCODE default Unknown::unknown() { 0x19: hw_mfpr({{ // this instruction is only valid in PAL mode if (!xc->inPalMode()) { - fault = Unimplemented_Opcode_Fault; + fault = UnimplementedOpcodeFault; } else { Ra = xc->readIpr(ipr_index, fault); @@ -738,7 +738,7 @@ decode OPCODE default Unknown::unknown() { 0x1d: hw_mtpr({{ // this instruction is only valid in PAL mode if (!xc->inPalMode()) { - fault = Unimplemented_Opcode_Fault; + fault = UnimplementedOpcodeFault; } else { xc->setIpr(ipr_index, Ra); diff --git a/arch/alpha/isa/fp.isa b/arch/alpha/isa/fp.isa index 0abc814be..7e81fb830 100644 --- a/arch/alpha/isa/fp.isa +++ b/arch/alpha/isa/fp.isa @@ -29,21 +29,21 @@ output exec {{ /// Check "FP enabled" machine status bit. Called when executing any FP /// instruction in full-system mode. - /// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault - /// if not. Non-full-system mode: always returns No_Fault. + /// @retval Full-system mode: NoFault if FP is enabled, FenFault + /// if not. Non-full-system mode: always returns NoFault. #if FULL_SYSTEM inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { - Fault fault = No_Fault; // dummy... this ipr access should not fault + Fault fault = NoFault; // dummy... this ipr access should not fault if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) { - fault = Fen_Fault; + fault = FloatEnableFault; } return fault; } #else inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { - return No_Fault; + return NoFault; } #endif }}; @@ -208,7 +208,7 @@ def template FloatingPointExecute {{ warnedOnTrapping = true; } - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; @@ -230,7 +230,7 @@ def template FloatingPointExecute {{ %(code)s; #endif - if (fault == No_Fault) { + if (fault == NoFault) { %(op_wb)s; } @@ -251,14 +251,14 @@ def template FPFixedRoundingExecute {{ warnedOnTrapping = true; } - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; - if (fault == No_Fault) { + if (fault == NoFault) { %(op_wb)s; } diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa index ef4d83ce2..b8d03c0be 100644 --- a/arch/alpha/isa/main.isa +++ b/arch/alpha/isa/main.isa @@ -33,6 +33,7 @@ output header {{ #include "config/ss_compatible_fp.hh" #include "cpu/static_inst.hh" +#include "arch/alpha/faults.hh" #include "mem/mem_req.hh" // some constructors use MemReq flags }}; @@ -44,6 +45,8 @@ output decoder {{ #include "cpu/exec_context.hh" // for Jump::branchTarget() #include <math.h> + +using namespace AlphaISA; }}; output exec {{ @@ -57,6 +60,8 @@ output exec {{ #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" + +using namespace AlphaISA; }}; //////////////////////////////////////////////////////////////////// @@ -178,7 +183,7 @@ output header {{ /** * Base class for all Alpha static instructions. */ - class AlphaStaticInst : public StaticInst<AlphaISA> + class AlphaStaticInst : public StaticInst { protected: @@ -195,7 +200,7 @@ output header {{ /// Constructor. AlphaStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) - : StaticInst<AlphaISA>(mnem, _machInst, __opClass) + : StaticInst(mnem, _machInst, __opClass) { } @@ -285,14 +290,14 @@ def template BasicExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; - if (fault == No_Fault) { + if (fault == NoFault) { %(op_wb)s; } @@ -351,6 +356,17 @@ output header {{ %(BasicExecDeclare)s }; + + /// Helper function for decoding nops. Substitute Nop object + /// for original inst passed in as arg (and delete latter). + static inline + AlphaStaticInst * + makeNop(AlphaStaticInst *inst) + { + AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); + delete inst; + return nop; + } }}; output decoder {{ @@ -363,24 +379,13 @@ output decoder {{ return csprintf("%-10s (%s)", "nop", originalDisassembly); #endif } - - /// Helper function for decoding nops. Substitute Nop object - /// for original inst passed in as arg (and delete latter). - inline - AlphaStaticInst * - makeNop(AlphaStaticInst *inst) - { - AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); - delete inst; - return nop; - } }}; output exec {{ Fault Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const { - return No_Fault; + return NoFault; } }}; diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa index 45afd378c..61d6ea8fa 100644 --- a/arch/alpha/isa/mem.isa +++ b/arch/alpha/isa/mem.isa @@ -37,14 +37,14 @@ output header {{ /// Memory request flags. See mem_req_base.hh. unsigned memAccessFlags; /// Pointer to EAComp object. - const StaticInstPtr<AlphaISA> eaCompPtr; + const StaticInstPtr eaCompPtr; /// Pointer to MemAcc object. - const StaticInstPtr<AlphaISA> memAccPtr; + const StaticInstPtr memAccPtr; /// Constructor Memory(const char *mnem, MachInst _machInst, OpClass __opClass, - StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, - StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr) + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) : AlphaStaticInst(mnem, _machInst, __opClass), memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr) { @@ -55,8 +55,8 @@ output header {{ public: - const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; } - const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; } + const StaticInstPtr &eaCompInst() const { return eaCompPtr; } + const StaticInstPtr &memAccInst() const { return memAccPtr; } }; /** @@ -71,8 +71,8 @@ output header {{ /// Constructor. MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass, - StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, - StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr) + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), disp(MEMDISP) { @@ -90,8 +90,8 @@ output header {{ protected: /// Constructor MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass, - StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, - StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr) + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) { } @@ -164,9 +164,24 @@ def template LoadStoreDeclare {{ %(class_name)s(MachInst machInst); %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s }; }}; + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + def template LoadStoreConstructor {{ /** TODO: change op_class to AddrGenOp or something (requires * creating new member of OpClass enum in op_class.hh, updating @@ -198,14 +213,14 @@ def template EACompExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; - if (fault == No_Fault) { + if (fault == NoFault) { %(op_wb)s; xc->setEA(EA); } @@ -220,19 +235,19 @@ def template LoadMemAccExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; EA = xc->getEA(); - if (fault == No_Fault) { + if (fault == NoFault) { fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); %(code)s; } - if (fault == No_Fault) { + if (fault == NoFault) { %(op_wb)s; } @@ -246,19 +261,66 @@ def template LoadExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(ea_code)s; - if (fault == No_Fault) { + if (fault == NoFault) { fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); %(memacc_code)s; } - if (fault == No_Fault) { + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + + memcpy(&Mem, data, sizeof(Mem)); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { %(op_wb)s; } @@ -273,7 +335,7 @@ def template StoreMemAccExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; uint64_t write_result = 0; %(fp_enable_check)s; @@ -281,21 +343,21 @@ def template StoreMemAccExecute {{ %(op_rd)s; EA = xc->getEA(); - if (fault == No_Fault) { + if (fault == NoFault) { %(code)s; } - if (fault == No_Fault) { + if (fault == NoFault) { fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, memAccessFlags, &write_result); if (traceData) { traceData->setData(Mem); } } - if (fault == No_Fault) { + if (fault == NoFault) { %(postacc_code)s; } - if (fault == No_Fault) { + if (fault == NoFault) { %(op_wb)s; } @@ -309,7 +371,7 @@ def template StoreExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; uint64_t write_result = 0; %(fp_enable_check)s; @@ -317,21 +379,75 @@ def template StoreExecute {{ %(op_rd)s; %(ea_code)s; - if (fault == No_Fault) { + if (fault == NoFault) { %(memacc_code)s; } - if (fault == No_Fault) { + if (fault == NoFault) { fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, memAccessFlags, &write_result); if (traceData) { traceData->setData(Mem); } } - if (fault == No_Fault) { + if (fault == NoFault) { %(postacc_code)s; } - if (fault == No_Fault) { + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&write_result, data, sizeof(write_result)); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { %(op_wb)s; } @@ -345,18 +461,18 @@ def template MiscMemAccExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; EA = xc->getEA(); - if (fault == No_Fault) { + if (fault == NoFault) { %(code)s; } - return No_Fault; + return NoFault; } }}; @@ -365,18 +481,39 @@ def template MiscExecute {{ Trace::InstRecord *traceData) const { Addr EA; - Fault fault = No_Fault; + Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(ea_code)s; - if (fault == No_Fault) { + if (fault == NoFault) { %(memacc_code)s; } - return No_Fault; + return NoFault; + } +}}; + +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + return NoFault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + + return NoFault; } }}; @@ -437,6 +574,34 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # for the post-access code. memacc_iop.postacc_code = postacc_cblk.code + # generate InstObjParams for InitiateAcc, CompleteAcc object + # The code used depends on the template being used + if (exec_template_base == 'Load'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(memacc_code + postacc_code) + elif (exec_template_base == 'Store'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(postacc_code) + else: + initiateacc_cblk = '' + completeacc_cblk = '' + + initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk, + inst_flags) + + completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk, + inst_flags) + + if (exec_template_base == 'Load'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + elif (exec_template_base == 'Store'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + # generate InstObjParams for unified execution cblk = CodeBlock(ea_code + memacc_code + postacc_code) iop = InstObjParams(name, Name, base_class, cblk, inst_flags) @@ -455,13 +620,17 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # select templates memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') # (header_output, decoder_output, decode_block, exec_output) return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), decode_template.subst(iop), EACompExecute.subst(ea_iop) + memAccExecTemplate.subst(memacc_iop) - + fullExecTemplate.subst(iop)) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(initiateacc_iop) + + completeAccTemplate.subst(completeacc_iop)) }}; diff --git a/arch/alpha/isa/pal.isa b/arch/alpha/isa/pal.isa index b68a7c19f..49e5bff12 100644 --- a/arch/alpha/isa/pal.isa +++ b/arch/alpha/isa/pal.isa @@ -149,8 +149,8 @@ output header {{ /// Constructor HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass, - StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, - StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr); + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr); std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; @@ -162,8 +162,8 @@ output decoder {{ inline HwLoadStore::HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass, - StaticInstPtr<AlphaISA> _eaCompPtr, - StaticInstPtr<AlphaISA> _memAccPtr) + StaticInstPtr _eaCompPtr, + StaticInstPtr _memAccPtr) : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), disp(HW_LDST_DISP) { diff --git a/arch/alpha/isa/unimp.isa b/arch/alpha/isa/unimp.isa index 767888157..de4ac3eaf 100644 --- a/arch/alpha/isa/unimp.isa +++ b/arch/alpha/isa/unimp.isa @@ -111,7 +111,7 @@ output exec {{ { panic("attempt to execute unimplemented instruction '%s' " "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE); - return Unimplemented_Opcode_Fault; + return UnimplementedOpcodeFault; } Fault @@ -123,7 +123,7 @@ output exec {{ warned = true; } - return No_Fault; + return NoFault; } }}; diff --git a/arch/alpha/isa/unknown.isa b/arch/alpha/isa/unknown.isa index 6eba5b4f9..4601b3684 100644 --- a/arch/alpha/isa/unknown.isa +++ b/arch/alpha/isa/unknown.isa @@ -42,7 +42,7 @@ output exec {{ { panic("attempt to execute unknown instruction " "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); - return Unimplemented_Opcode_Fault; + return UnimplementedOpcodeFault; } }}; diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index a17cde49b..f47e90f86 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -32,10 +32,11 @@ namespace LittleEndianGuest {} using namespace LittleEndianGuest; -#include "arch/alpha/faults.hh" +//#include "arch/alpha/faults.hh" #include "base/misc.hh" #include "config/full_system.hh" #include "sim/host.hh" +#include "sim/faults.hh" class FastCPU; class FullCPU; @@ -43,20 +44,19 @@ class Checkpoint; #define TARGET_ALPHA -template <class ISA> class StaticInst; -template <class ISA> class StaticInstPtr; +class StaticInst; +class StaticInstPtr; namespace EV5 { int DTB_ASN_ASN(uint64_t reg); int ITB_ASN_ASN(uint64_t reg); } -class AlphaISA +namespace AlphaISA { - public: typedef uint32_t MachInst; - typedef uint64_t Addr; +// typedef uint64_t Addr; typedef uint8_t RegIndex; enum { @@ -132,10 +132,10 @@ class AlphaISA Addr lock_addr; // lock address for LL/SC } MiscRegFile; -static const Addr PageShift = 13; -static const Addr PageBytes = ULL(1) << PageShift; -static const Addr PageMask = ~(PageBytes - 1); -static const Addr PageOffset = PageBytes - 1; +extern const Addr PageShift; +extern const Addr PageBytes; +extern const Addr PageMask; +extern const Addr PageOffset; #if FULL_SYSTEM @@ -183,10 +183,10 @@ static const Addr PageOffset = PageBytes - 1; void unserialize(Checkpoint *cp, const std::string §ion); }; - static StaticInstPtr<AlphaISA> decodeInst(MachInst); + StaticInstPtr decodeInst(MachInst); // return a no-op instruction... used for instruction fetch faults - static const MachInst NoopMachInst; + extern const MachInst NoopMachInst; enum annotes { ANNOTE_NONE = 0, @@ -241,10 +241,10 @@ static const Addr PageOffset = PageBytes - 1; // Machine operations - static void saveMachineReg(AnyReg &savereg, const RegFile ®_file, + void saveMachineReg(AnyReg &savereg, const RegFile ®_file, int regnum); - static void restoreMachineReg(RegFile ®s, const AnyReg ®, + void restoreMachineReg(RegFile ®s, const AnyReg ®, int regnum); #if 0 @@ -262,41 +262,41 @@ static const Addr PageOffset = PageBytes - 1; * @param xc The execution context. */ template <class XC> - static void zeroRegisters(XC *xc); + void zeroRegisters(XC *xc); + + +//typedef AlphaISA TheISA; + +//typedef TheISA::MachInst MachInst; +//typedef TheISA::Addr Addr; +//typedef TheISA::RegIndex RegIndex; +//typedef TheISA::IntReg IntReg; +//typedef TheISA::IntRegFile IntRegFile; +//typedef TheISA::FloatReg FloatReg; +//typedef TheISA::FloatRegFile FloatRegFile; +//typedef TheISA::MiscReg MiscReg; +//typedef TheISA::MiscRegFile MiscRegFile; +//typedef TheISA::AnyReg AnyReg; +//typedef TheISA::RegFile RegFile; + +//const int NumIntRegs = TheISA::NumIntRegs; +//const int NumFloatRegs = TheISA::NumFloatRegs; +//const int NumMiscRegs = TheISA::NumMiscRegs; +//const int TotalNumRegs = TheISA::TotalNumRegs; +//const int VMPageSize = TheISA::VMPageSize; +//const int LogVMPageSize = TheISA::LogVMPageSize; +//const int ZeroReg = TheISA::ZeroReg; +//const int StackPointerReg = TheISA::StackPointerReg; +//const int GlobalPointerReg = TheISA::GlobalPointerReg; +//const int ReturnAddressReg = TheISA::ReturnAddressReg; +//const int ReturnValueReg = TheISA::ReturnValueReg; +//const int ArgumentReg0 = TheISA::ArgumentReg0; +//const int ArgumentReg1 = TheISA::ArgumentReg1; +//const int ArgumentReg2 = TheISA::ArgumentReg2; +//const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt; +const Addr MaxAddr = (Addr)-1; }; - -typedef AlphaISA TheISA; - -typedef TheISA::MachInst MachInst; -typedef TheISA::Addr Addr; -typedef TheISA::RegIndex RegIndex; -typedef TheISA::IntReg IntReg; -typedef TheISA::IntRegFile IntRegFile; -typedef TheISA::FloatReg FloatReg; -typedef TheISA::FloatRegFile FloatRegFile; -typedef TheISA::MiscReg MiscReg; -typedef TheISA::MiscRegFile MiscRegFile; -typedef TheISA::AnyReg AnyReg; -typedef TheISA::RegFile RegFile; - -const int NumIntRegs = TheISA::NumIntRegs; -const int NumFloatRegs = TheISA::NumFloatRegs; -const int NumMiscRegs = TheISA::NumMiscRegs; -const int TotalNumRegs = TheISA::TotalNumRegs; -const int VMPageSize = TheISA::VMPageSize; -const int LogVMPageSize = TheISA::LogVMPageSize; -const int ZeroReg = TheISA::ZeroReg; -const int StackPointerReg = TheISA::StackPointerReg; -const int GlobalPointerReg = TheISA::GlobalPointerReg; -const int ReturnAddressReg = TheISA::ReturnAddressReg; -const int ReturnValueReg = TheISA::ReturnValueReg; -const int ArgumentReg0 = TheISA::ArgumentReg0; -const int ArgumentReg1 = TheISA::ArgumentReg1; -const int ArgumentReg2 = TheISA::ArgumentReg2; -const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt; -const int MaxAddr = (Addr)-1; - #if !FULL_SYSTEM class SyscallReturn { public: @@ -335,9 +335,9 @@ class SyscallReturn { #if FULL_SYSTEM -typedef TheISA::InternalProcReg InternalProcReg; -const int NumInternalProcRegs = TheISA::NumInternalProcRegs; -const int NumInterruptLevels = TheISA::NumInterruptLevels; +//typedef TheISA::InternalProcReg InternalProcReg; +//const int NumInternalProcRegs = TheISA::NumInternalProcRegs; +//const int NumInterruptLevels = TheISA::NumInterruptLevels; #include "arch/alpha/ev5.hh" #endif diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc index 5a8df3d35..30ed07d9d 100644 --- a/arch/alpha/stacktrace.cc +++ b/arch/alpha/stacktrace.cc @@ -37,6 +37,7 @@ #include "cpu/exec_context.hh" using namespace std; +using namespace AlphaISA; ProcessInfo::ProcessInfo(ExecContext *_xc) : xc(_xc) @@ -108,7 +109,7 @@ StackTrace::StackTrace() { } -StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst) +StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst) : xc(0), stack(64) { trace(_xc, inst); diff --git a/arch/alpha/stacktrace.hh b/arch/alpha/stacktrace.hh index 244e574b6..1d8d97a79 100644 --- a/arch/alpha/stacktrace.hh +++ b/arch/alpha/stacktrace.hh @@ -56,6 +56,8 @@ class ProcessInfo class StackTrace { + protected: + typedef TheISA::MachInst MachInst; private: ExecContext *xc; std::vector<Addr> stack; @@ -70,7 +72,7 @@ class StackTrace public: StackTrace(); - StackTrace(ExecContext *xc, StaticInstPtr<TheISA> inst); + StackTrace(ExecContext *xc, StaticInstPtr inst); ~StackTrace(); void clear() @@ -80,7 +82,7 @@ class StackTrace } bool valid() const { return xc != NULL; } - bool trace(ExecContext *xc, StaticInstPtr<TheISA> inst); + bool trace(ExecContext *xc, StaticInstPtr inst); public: const std::vector<Addr> &getstack() const { return stack; } @@ -102,7 +104,7 @@ class StackTrace }; inline bool -StackTrace::trace(ExecContext *xc, StaticInstPtr<TheISA> inst) +StackTrace::trace(ExecContext *xc, StaticInstPtr inst) { if (!inst->isCall() && !inst->isReturn()) return false; diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index 27014164c..3ffa4bd14 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -34,6 +34,7 @@ #include "mem/functional/physical.hh" using namespace std; +using namespace AlphaISA; AlphaISA::PageTableEntry kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr) diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 030bb5a7c..a2bf31a0c 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -224,7 +224,7 @@ def p_specification(t): namespace = isa_name + "Inst" # wrap the decode block as a function definition t[4].wrap_decode_block(''' -StaticInstPtr<%(isa_name)s> +StaticInstPtr %(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst) { using namespace %(namespace)s; @@ -1138,6 +1138,7 @@ class Operand(object): # template must be careful not to use it if it doesn't apply. if self.isMem(): self.mem_acc_size = self.makeAccSize() + self.mem_acc_type = self.ctype # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the @@ -1150,13 +1151,17 @@ class Operand(object): if self.is_src: self.op_rd = self.makeRead() + self.op_src_decl = self.makeDecl() else: self.op_rd = '' + self.op_src_decl = '' if self.is_dest: self.op_wb = self.makeWrite() + self.op_dest_decl = self.makeDecl() else: self.op_wb = '' + self.op_dest_decl = '' def isMem(self): return 0 @@ -1346,6 +1351,7 @@ class MemOperand(Operand): def makeAccSize(self): return self.size + class NPCOperand(Operand): def makeConstructor(self): return '' @@ -1356,6 +1362,15 @@ class NPCOperand(Operand): def makeWrite(self): return 'xc->setNextPC(%s);\n' % self.base_name +class NNPCOperand(Operand): + def makeConstructor(self): + return '' + + def makeRead(self): + return '%s = xc->readPC() + 8;\n' % self.base_name + + def makeWrite(self): + return 'xc->setNextNPC(%s);\n' % self.base_name def buildOperandNameMap(userDict, lineno): global operandNameMap @@ -1589,6 +1604,14 @@ class CodeBlock: self.op_decl = self.operands.concatAttrStrings('op_decl') + is_src = lambda op: op.is_src + is_dest = lambda op: op.is_dest + + self.op_src_decl = \ + self.operands.concatSomeAttrStrings(is_src, 'op_src_decl') + self.op_dest_decl = \ + self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') + self.op_rd = self.operands.concatAttrStrings('op_rd') self.op_wb = self.operands.concatAttrStrings('op_wb') @@ -1596,6 +1619,7 @@ class CodeBlock: if self.operands.memOperand: self.mem_acc_size = self.operands.memOperand.mem_acc_size + self.mem_acc_type = self.operands.memOperand.mem_acc_type # Make a basic guess on the operand class (function unit type). # These are good enough for most cases, and will be overridden @@ -1672,6 +1696,8 @@ namespace %(namespace)s { %(namespace_output)s } // namespace %(namespace)s + +%(decode_function)s ''' @@ -1725,7 +1751,7 @@ def preprocess_isa_desc(isa_desc): # # Read in and parse the ISA description. # -def parse_isa_desc(isa_desc_file, output_dir, include_path): +def parse_isa_desc(isa_desc_file, output_dir): # set a global var for the input filename... used in error messages global input_filename input_filename = isa_desc_file @@ -1751,24 +1777,27 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): includes = '#include "base/bitfield.hh" // for bitfield support' global_output = global_code.header_output namespace_output = namespace_code.header_output + decode_function = '' update_if_needed(output_dir + '/decoder.hh', file_template % vars()) # generate decoder.cc - includes = '#include "%s/decoder.hh"' % include_path + includes = '#include "decoder.hh"' global_output = global_code.decoder_output namespace_output = namespace_code.decoder_output - namespace_output += namespace_code.decode_block + # namespace_output += namespace_code.decode_block + decode_function = namespace_code.decode_block update_if_needed(output_dir + '/decoder.cc', file_template % vars()) # generate per-cpu exec files for cpu in CpuModel.list: - includes = '#include "%s/decoder.hh"\n' % include_path + includes = '#include "decoder.hh"\n' includes += cpu.includes global_output = global_code.exec_output[cpu.name] namespace_output = namespace_code.exec_output[cpu.name] + decode_function = '' update_if_needed(output_dir + '/' + cpu.filename, file_template % vars()) # Called as script: get args from command line. if __name__ == '__main__': - parse_isa_desc(sys.argv[1], sys.argv[2], sys.argv[3]) + parse_isa_desc(sys.argv[1], sys.argv[2]) diff --git a/arch/isa_specific.hh b/arch/isa_specific.hh new file mode 100644 index 000000000..44f8e9d64 --- /dev/null +++ b/arch/isa_specific.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ARCH_ISA_SPECIFIC_HH__ +#define __ARCH_ISA_SPECIFIC_HH__ + +//This file provides a mechanism for other source code to bring in +//files from the ISA being compiled with + +//These are constants so you can selective compile code based on the isa +//To use them, do something like +// +//#if THE_ISA == YOUR_FAVORITE_ISA +// conditional_code +//#endif +// +//Note that this is how this file sets up the other isa "hooks" + +//These macros have numerical values because otherwise the preprocessor +//would treat them as 0 in comparisons. +#define ALPHA_ISA 21064 +#define SPARC_ISA 42 +#define MIPS_ISA 1337 + +//These tell the preprocessor where to find the files of a particular +//ISA, and set the "TheISA" macro for use elsewhere. +#if THE_ISA == ALPHA_ISA + #define TheISA AlphaISA +#elif THE_ISA == SPARC_ISA + #define TheISA SparcISA +#elif THE_ISA == MIPS_ISA + #define TheISA MipsISA +#else + #error "THE_ISA not set" +#endif + +#endif diff --git a/arch/mips/SConscript b/arch/mips/SConscript new file mode 100644 index 000000000..b8efa7ef9 --- /dev/null +++ b/arch/mips/SConscript @@ -0,0 +1,83 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import sys +from os.path import isdir + +# Import build environment variable from SConstruct. +Import('env') + +################################################### +# +# Define needed sources. +# +################################################### + +# Base sources used by all configurations. +base_sources = Split(''' + faults.cc + isa_traits.cc + ''') + +# Full-system sources +full_system_sources = Split(''' + memory.cc + arguments.cc + mips34k.cc + osfpal.cc + stacktrace.cc + vtophys.cc + ''') + +# Syscall emulation (non-full-system) sources +syscall_emulation_sources = Split(''' + common_syscall_emul.cc + linux_process.cc + tru64_process.cc + ''') + +# Set up complete list of sources based on configuration. +sources = base_sources + +if env['FULL_SYSTEM']: + sources += full_system_sources +else: + sources += syscall_emulation_sources + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +# Add in files generated by the ISA description. +isa_desc_files = env.ISADesc('isa/main.isa') +# Only non-header files need to be compiled. +isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] +sources += isa_desc_sources + +Return('sources') diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa new file mode 100644 index 000000000..846d161b9 --- /dev/null +++ b/arch/mips/isa/base.isa @@ -0,0 +1,63 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Base class for MIPS instructions, and some support functions +// + +//Outputs to decoder.hh +output header {{ + /** + * Base class for all MIPS static instructions. + */ + class MipsStaticInst : public StaticInst<MIPSISA> + { + protected: + + // Constructor. + MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + : StaticInst<MIPSISA>(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +//Ouputs to decoder.cc +output decoder {{ + + std::string MipsStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if(_numSrcRegs > 0) + { + printReg(ss, _srcRegIdx[0]); + } + if(_numSrcRegs > 1) + { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + // just print the first dest... if there's a second one, + // it's generally implicit + if(_numDestRegs > 0) + { + if(_numSrcRegs > 0) + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } + +}}; + diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa index bead9c151..532b3793a 100644 --- a/arch/mips/isa/bitfields.isa +++ b/arch/mips/isa/bitfields.isa @@ -1,3 +1,5 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // // Bitfield definitions. @@ -41,7 +43,7 @@ def bitfield SC < 5: 5>; // Branch format def bitfield OFFSET <15: 0>; // displacement -// Memory-format jumps +// Jmp format def bitfield JMPTARG <25: 0>; def bitfield JMPHINT <10: 6>; diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa index 2ec7da805..7dd08ac49 100644 --- a/arch/mips/isa/decoder.isa +++ b/arch/mips/isa/decoder.isa @@ -1,3 +1,5 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // // The actual MIPS32 ISA decoder @@ -9,193 +11,207 @@ // //@todo: Distinguish "unknown/future" use insts from "reserved" // ones -decode OPCODE_HI default FailUnimpl::unknown() { +decode OPCODE_HI default Unknown::unknown() { // Derived From ... Table A-2 MIPS32 ISA Manual - 0x0: decode OPCODE_LO default FailUnimpl::reserved(){ + 0x0: decode OPCODE_LO { 0x0: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { - 0x1: decode MOVCI { - format BasicOp { - 0: movf({{ if( xc->miscRegs.fpcr == 0) Rd = Rs}}); - 1: movt({{ if( xc->miscRegs.fpcr == 1) Rd = Rs}}); + 0x1: decode MOVCI { + format BasicOp { + 0: movf({{ if( xc->miscRegs.fpcr == 0) Rd = Rs}}); + 1: movt({{ if( xc->miscRegs.fpcr == 1) Rd = Rs}}); + } } - } - format BasicOp { + format BasicOp { - //Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields - //are used to distinguish among the SLL, NOP, SSNOP and EHB functions." + //Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields + //are used to distinguish among the SLL, NOP, SSNOP and EHB functions." - 0x0: sll({{ Rd = Rt.uw << SA; }}); + 0x0: sll({{ Rd = Rt.uw << SA; }}); - 0x2: decode SRL { - 0: srl({{ Rd = Rt.uw >> SA; }}); + 0x2: decode SRL { + 0: srl({{ Rd = Rt.uw >> SA; }}); - //Hardcoded assuming 32-bit ISA, probably need parameter here - 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}}); - } + //Hardcoded assuming 32-bit ISA, probably need parameter here + 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}}); + } - 0x3: sra({{ Rd = Rt.sw >> SA; }}); + 0x3: sra({{ Rd = Rt.sw >> SA; }}); - 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }}); + 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }}); - 0x6: decode SRLV { - 0: srlv({{ Rd = Rt.uw >> Rs<4:0>; }}); + 0x6: decode SRLV { + 0: srlv({{ Rd = Rt.uw >> Rs<4:0>; }}); - //Hardcoded assuming 32-bit ISA, probably need parameter here - 1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}}); - } + //Hardcoded assuming 32-bit ISA, probably need parameter here + 1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}}); + } - 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }}); - } + 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }}); + } } 0x1: decode FUNCTION_LO { - //Table A-3 Note: "Specific encodings of the hint field are used - //to distinguish JR from JR.HB and JALR from JALR.HB" - format Jump { - 0x0: jr(IsReturn); - 0x1: jalr(IsCall,IsReturn); - } - - format BasicOp { - 0x2: movz({{ if (Rt == 0) Rd = Rs; }}); - 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); - } - - format WarnUnimpl { - 0x4: syscall({{ xc->syscall()}},IsNonSpeculative); - 0x5: break({{ }}); - 0x7: sync({{ }}); - } + //Table A-3 Note: "Specific encodings of the hint field are used + //to distinguish JR from JR.HB and JALR from JALR.HB" + format Jump { + 0x0: decode HINT { + 0:jr({{ NNPC = Rs; }},IsReturn); + + 1:jr_hb({{ NNPC = Rs; clear_exe_inst_hazards(); }},IsReturn); + } + + 0x1: decode HINT { + 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn); + + 1: jalr_hb({{ NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn); + } + } + + format BasicOp { + 0x2: movz({{ if (Rt == 0) Rd = Rs; }}); + 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); + } + + format WarnUnimpl { + 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative + 0x5: break(); + 0x7: sync(); + } } 0x2: decode FUNCTION_LO { - format BasicOp { - 0x0: mfhi({{ Rd = xc->miscRegs.hi; }}); - 0x1: mthi({{ xc->miscRegs.hi = Rs; }}); - 0x2: mflo({{ Rd = xc->miscRegs.lo; }}); - 0x3: mtlo({{ xc->miscRegs.lo = Rs; }}); - } - }; + format BasicOp { + 0x0: mfhi({{ Rd = xc->miscRegs.hi; }}); + 0x1: mthi({{ xc->miscRegs.hi = Rs; }}); + 0x2: mflo({{ Rd = xc->miscRegs.lo; }}); + 0x3: mtlo({{ xc->miscRegs.lo = Rs; }}); + } + } 0x3: decode FUNCTION_LO { - format IntOp { - 0x0: mult({{ + format IntOp { + 0x0: mult({{ INT64 temp1 = Rs.sw * Rt.sw; xc->miscRegs.hi->temp1<63:32>; - xc->miscRegs.lo->temp1<31:0> - }}); + xc->miscRegs.lo->temp1<31:0>; + }}); - 0x1: multu({{ + 0x1: multu({{ INT64 temp1 = Rs.uw * Rt.uw; xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - Rd.sw = Rs.uw * Rt.uw; - }}); + Rd.sw = Rs.uw * Rt.uw; + }}); - 0x2: div({{ + 0x2: div({{ xc->miscRegs.hi = Rs.sw % Rt.sw; xc->miscRegs.lo = Rs.sw / Rt.sw; - }}); + }}); - 0x3: divu({{ + 0x3: divu({{ xc->miscRegs.hi = Rs.uw % Rt.uw; xc->miscRegs.lo = Rs.uw / Rt.uw; - }}); - } - }; + }}); + } + } 0x4: decode FUNCTION_LO { - format IntOp { - 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;}}); - 0x1: addu({{ Rd.uw = Rs.uw + Rt.uw;}}); - 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw;}}); - 0x3: subu({{ Rd.uw = Rs.uw - Rt.uw;}}); - 0x4: and({{ Rd.sw = Rs.uw & Rt.uw;}}); - 0x5: or({{ Rd.sw = Rs.uw | Rt.uw;}}); - 0x6: xor({{ Rd.sw = Rs.uw ^ Rt.uw;}}); - 0x7: nor({{ Rd.sw = ~(Rs.uw | Rt.uw);}}); - } + format IntOp { + 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;}}); + 0x1: addu({{ Rd.uw = Rs.uw + Rt.uw;}}); + 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw;}}); + 0x3: subu({{ Rd.uw = Rs.uw - Rt.uw;}}); + 0x4: and({{ Rd.sw = Rs.uw & Rt.uw;}}); + 0x5: or({{ Rd.sw = Rs.uw | Rt.uw;}}); + 0x6: xor({{ Rd.sw = Rs.uw ^ Rt.uw;}}); + 0x7: nor({{ Rd.sw = ~(Rs.uw | Rt.uw);}}); + } } 0x5: decode FUNCTION_LO { - format IntOp{ - 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}}); - 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}}); - } - }; + format IntOp{ + 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}}); + 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}}); + } + } 0x6: decode FUNCTION_LO { - format Trap { - 0x0: tge({{ cond = (Rs.sw >= Rt.sw); }}); - 0x1: tgeu({{ cond = (Rs.uw >= Rt.uw); }}); - 0x2: tlt({{ cond = (Rs.sw < Rt.sw); }}); - 0x3: tltu({{ cond = (Rs.uw >= Rt.uw); }}); - 0x4: teq({{ cond = (Rs.sw == Rt.sw); }}); - 0x6: tne({{ cond = (Rs.sw != Rt.sw); }}); - } + format Trap { + 0x0: tge({{ cond = (Rs.sw >= Rt.sw); }}); + 0x1: tgeu({{ cond = (Rs.uw >= Rt.uw); }}); + 0x2: tlt({{ cond = (Rs.sw < Rt.sw); }}); + 0x3: tltu({{ cond = (Rs.uw >= Rt.uw); }}); + 0x4: teq({{ cond = (Rs.sw == Rt.sw); }}); + 0x6: tne({{ cond = (Rs.sw != Rt.sw); }}); + } } } 0x1: decode REGIMM_HI { 0x0: decode REGIMM_LO { - format Branch { - 0x0: bltz({{ cond = (Rs.sq < 0); }}); - 0x1: bgez({{ cond = (Rs.sq >= 0); }}); - - //MIPS obsolete instructions - 0x2: bltzl({{ cond = (Rs.sq < 0); }}); - 0x3: bgezl({{ cond = (Rs.sq >= 0); }}); - } + format Branch { + 0x0: bltz({{ cond = (Rs.sw < 0); }}); + 0x1: bgez({{ cond = (Rs.sw >= 0); }}); + } + + format BranchLikely { + //MIPS obsolete instructions + 0x2: bltzl({{ cond = (Rs.sw < 0); }}); + 0x3: bgezl({{ cond = (Rs.sw >= 0); }}); + } } 0x1: decode REGIMM_LO { - format Trap { - 0x0: tgei({{ cond = (Rs.sw >= INTIMM; }}); - 0x1: tgeiu({{ cond = (Rs.uw < INTIMM); }}); - 0x2: tlti({{ cond = (Rs.sw < INTIMM); }}); - 0x3: tltiu({{ cond = (Rs.uw < INTIMM); }}); - 0x4: teqi({{ cond = (Rs.sw == INTIMM); }}); - 0x6: tnei({{ cond = (Rs.sw != INTIMM); }}); - } + format Trap { + 0x0: tgei( {{ cond = (Rs.sw >= INTIMM); }}); + 0x1: tgeiu({{ cond = (Rs.uw >= INTIMM); }}); + 0x2: tlti( {{ cond = (Rs.sw < INTIMM); }}); + 0x3: tltiu({{ cond = (Rs.uw < INTIMM); }}); + 0x4: teqi( {{ cond = (Rs.sw == INTIMM);}}); + 0x6: tnei( {{ cond = (Rs.sw != INTIMM);}}); + } } 0x2: decode REGIMM_LO { - format Branch { - 0x0: bltzal({{ cond = (Rs.sq < 0); }}); - 0x1: bgezal({{ cond = (Rs.sq >= 0); }}); - - //MIPS obsolete instructions - 0x2: bltzall({{ cond = (Rs.sq < 0); }}); - 0x3: bgezall({{ cond = (Rs.sq >= 0); }}); - } + format Branch { + 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsLink); + 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsLink); + } + + format BranchLikely { + //Will be removed in future MIPS releases + 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsLink); + 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsLink); + } } 0x3: decode REGIMM_LO { - format WarnUnimpl { - 0x7: synci({{ }}); - } + format WarnUnimpl { + 0x7: synci(); + } } } format Jump { - 0x2: j(); - 0x3: jal(IsCall); + 0x2: j({{ NNPC = (NPC & 0xF0000000) & (0x00000000 & JMPTARG << 2);}}); + + 0x3: jal({{ NNPC = (NPC & 0xF0000000) & (0x00000000 & JMPTARG << 2);}},IsCall,IsReturn); } format Branch { - 0x4: beq({{ cond = (Rs.sq == 0); }}); - 0x5: bne({{ cond = (Rs.sq != 0); }}); - 0x6: blez({{ cond = (Rs.sq <= 0); }}); - 0x7: bgtz({{ cond = (Rs.sq > 0); }}); + 0x4: beq({{ cond = (Rs.sw == 0); }}); + 0x5: bne({{ cond = (Rs.sw != 0); }}); + 0x6: blez({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtz({{ cond = (Rs.sw > 0); }}); } - }; + } - 0x1: decode OPCODE_LO default FailUnimpl::reserved(){ + 0x1: decode OPCODE_LO { format IntOp { 0x0: addi({{ Rt.sw = Rs.sw + INTIMM; }}); 0x1: addiu({{ Rt.uw = Rs.uw + INTIMM;}}); @@ -205,540 +221,539 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x5: ori({{ Rt.sw = Rs.sw | INTIMM;}}); 0x6: xori({{ Rt.sw = Rs.sw ^ INTIMM;}}); 0x7: lui({{ Rt = INTIMM << 16}}); - }; - }; - - 0x2: decode OPCODE_LO default FailUnimpl::reserved(){ + } + } - //Table A-11 MIPS32 COP0 Encoding of rs Field - 0x0: decode RS_MSB { - 0x0: decode RS { + 0x2: decode OPCODE_LO { - format BasicOp { - 0x0: mfc0({{ + //Table A-11 MIPS32 COP0 Encoding of rs Field + 0x0: decode RS_MSB { + 0x0: decode RS { + format BasicOp { + 0x0: mfc0({{ //The contents of the coprocessor 0 register specified by the //combination of rd and sel are loaded into general register //rt. Note that not all coprocessor 0 registers support the //sel field. In those instances, the sel field must be zero. if (SEL > 0) - panic("Can't Handle Cop0 with register select yet\n"); + panic("Can't Handle Cop0 with register select yet\n"); uint64_t reg_num = Rd.uw; Rt = xc->miscRegs.cop0[reg_num]; - }}); + }}); - 0x4: mtc0({{ + 0x4: mtc0({{ //The contents of the coprocessor 0 register specified by the //combination of rd and sel are loaded into general register //rt. Note that not all coprocessor 0 registers support the //sel field. In those instances, the sel field must be zero. if (SEL > 0) - panic("Can't Handle Cop0 with register select yet\n"); + panic("Can't Handle Cop0 with register select yet\n"); uint64_t reg_num = Rd.uw; xc->miscRegs.cop0[reg_num] = Rt; - }}); + }}); - 0x8: mftr({{ + 0x8: mftr({{ //The contents of the coprocessor 0 register specified by the //combination of rd and sel are loaded into general register //rt. Note that not all coprocessor 0 registers support the //sel field. In those instances, the sel field must be zero. //MT Code Needed Here - }}); + }}); - 0xC: mttr({{ + 0xC: mttr({{ //The contents of the coprocessor 0 register specified by the //combination of rd and sel are loaded into general register //rt. Note that not all coprocessor 0 registers support the //sel field. In those instances, the sel field must be zero. //MT Code Needed Here - }}); + }}); - 0xA: rdpgpr({{ + 0xA: rdpgpr({{ //Accessing Previous Shadow Set Register Number uint64_t prev = xc->miscRegs.cop0[SRSCtl][PSS]; uint64_t reg_num = Rt.uw; Rd = xc->shadowIntRegFile[prev][reg_num]; - }}); - } + }}); - 0xB: decode RD { + 0xB: decode RD { - 0x0: decode SC { - format BasicOp { - 0x0: dvpe({{ - Rt.sw = xc->miscRegs.cop0.MVPControl; - xc->miscRegs.cop0.MVPControl[EVP] = 0; - }}); + 0x0: decode SC { + 0x0: dvpe({{ + Rt.sw = xc->miscRegs.cop0.MVPControl; + xc->miscRegs.cop0.MVPControl[EVP] = 0; + }}); - 0x1: evpe({{ - Rt.sw = xc->miscRegs.cop0.MVPControl; - xc->miscRegs.cop0.MVPControl[EVP] = 1; - }}); - } - } + 0x1: evpe({{ + Rt.sw = xc->miscRegs.cop0.MVPControl; + xc->miscRegs.cop0.MVPControl[EVP] = 1; + }}); + } - 0x1: decode SC { - format BasicOp { - 0x0: dmt({{ - Rt.sw = xc->miscRegs.cop0.VPEControl; - xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 0; - }}); + 0x1: decode SC { + 0x0: dmt({{ + Rt.sw = xc->miscRegs.cop0.VPEControl; + xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 0; + }}); - 0x1: emt({{ - Rt.sw = xc->miscRegs.cop0.VPEControl; - xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 1; - }}); - } - } + 0x1: emt({{ + Rt.sw = xc->miscRegs.cop0.VPEControl; + xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 1; + }}); + } - 0xC: decode SC { - format BasicOp { - 0x0: di({{ - Rt.sw = xc->miscRegs.cop0.Status; - xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 0; - }}); + 0xC: decode SC { + 0x0: di({{ + Rt.sw = xc->miscRegs.cop0.Status; + xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 0; + }}); - 0x1: ei({{ - Rt.sw = xc->miscRegs.cop0.Status; - xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 1; - }}); - } - } - } + 0x1: ei({{ + Rt.sw = xc->miscRegs.cop0.Status; + xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 1; + }}); + } + } - 0xE: BasicOp::wrpgpr({{ + 0xE: wrpgpr({{ //Accessing Previous Shadow Set Register Number uint64_t prev = xc->miscRegs.cop0[SRSCtl][PSS]; uint64_t reg_num = Rd.uw; xc->shadowIntRegFile[prev][reg_num] = Rt; - }}); - } - - //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO - 0x1: decode FUNCTION { - format Trap { - 0x01: tlbr({{ }}); - 0x02: tlbwi({{ }}); - 0x06: tlbwr({{ }}); - 0x08: tlbp({{ }}); - } - - format WarnUnimpl { - 0x18: eret({{ }}); - 0x1F: deret({{ }}); - 0x20: wait({{ }}); - } - } - } - - //Table A-13 MIPS32 COP1 Encoding of rs Field - 0x1: decode RS_MSB { - - 0x0: decode RS_HI { - 0x0: decode RS_LO { - format FloatOp { - 0x0: mfc1({{ Rt = Fs<31:0>; }}); - 0x2: cfc1({{ Rt = xc->miscRegs.fpcr[Fs];}}); - 0x3: mfhc1({{ Rt = Fs<63:32>;}}); - 0x4: mtc1({{ Fs<31:0> = Rt}}); - 0x6: ctc1({{ xc->miscRegs.fpcr[Fs] = Rt;}}); - 0x7: mftc1({{ Fs<63:32> = Rt}}); - } - } - - 0x1: decode ND { - 0x0: decode TF { - format Branch { - 0x0: bc1f({{ cond = (xc->miscRegs.fpcr == 0); }}); - 0x1: bc1t({{ cond = (xc->miscRegs.fpcr == 1); }}); - } + }}); + } } - 0x1: decode TF { - format Branch { - 0x0: bc1fl({{ cond = (xc->miscRegs.fpcr == 0); }}); - 0x1: bc1tl({{ cond = (xc->miscRegs.fpcr == 1); }}); - } + //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO + 0x1: decode FUNCTION { + format Trap { + 0x01: tlbr({{ }}); + 0x02: tlbwi({{ }}); + 0x06: tlbwr({{ }}); + 0x08: tlbp({{ }}); + } + + format WarnUnimpl { + 0x18: eret(); + 0x1F: deret(); + 0x20: wait(); + } } - } } - 0x1: decode RS_HI { - 0x2: decode RS_LO { + //Table A-13 MIPS32 COP1 Encoding of rs Field + 0x1: decode RS_MSB { - //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S - //(( single-word )) 0x0: decode RS_HI { - 0x0: decode RS_LO { - format FloatOp { - 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); - 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); - 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); - 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); - 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); - 0x5: abss({{ Fd.sf = abs(Fs.sf);}}); - 0x6: movs({{ Fd.sf = Fs.sf;}}); - 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); - } - } - - 0x1: decode RS_LO { - //only legal for 64 bit - format Float64Op { - 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); - 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); - 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}}); - 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}}); - } - - format FloatOp { - 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}}); - 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}}); - 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}}); - 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}}); - } - } - - 0x2: decode RS_LO { - 0x1: decode MOVCF { - format FloatOp { - 0x0: movfs({{ if ( FPConditionCode(CC) == 0 ) Fd = Fs; }}); - 0x1: movts({{ if ( FPConditionCode(CC) == 1 ) Fd = Fs;}}); - } + 0x0: decode RS_LO { + format FloatOp { + 0x0: mfc1({{ Rt = Fs<31:0>; }}); + 0x2: cfc1({{ Rt = xc->miscRegs.fpcr[Fs];}}); + 0x3: mfhc1({{ Rt = Fs<63:32>;}}); + 0x4: mtc1({{ Fs<31:0> = Rt}}); + 0x6: ctc1({{ xc->miscRegs.fpcr[Fs] = Rt;}}); + 0x7: mftc1({{ Fs<63:32> = Rt}}); + } } - format BasicOp { - 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); - 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); - } + 0x1: decode ND { + 0x0: decode TF { + format Branch { + 0x0: bc1f({{ cond = (xc->miscRegs.fpcr == 0); }}); + 0x1: bc1t({{ cond = (xc->miscRegs.fpcr == 1); }}); + } + } - format Float64Op { - 0x2: recips({{ Fd = 1 / Fs; }}); - 0x3: rsqrts{{ Fd = 1 / sqrt(Fs); }}); + 0x1: decode TF { + format BranchLikely { + 0x0: bc1fl({{ cond = (xc->miscRegs.fpcr == 0); }}); + 0x1: bc1tl({{ cond = (xc->miscRegs.fpcr == 1); }}); + } + } } - } + } + + 0x1: decode RS_HI { + 0x2: decode RS_LO { + + //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S + //(( single-word )) + 0x0: decode RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); + 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); + 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); + 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); + 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); + 0x5: abss({{ Fd.sf = abs(Fs.sf);}}); + 0x6: movs({{ Fd.sf = Fs.sf;}}); + 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); + } + } - 0x4: decode RS_LO { - 0x1: cvt_d_s({{ int rnd_mode = xc->miscRegs.fcsr; + 0x1: decode RS_LO { + //only legal for 64 bit-FP + format Float64Op { + 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); + 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); + 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}}); + 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}}); + } + + format FloatOp { + 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}}); + 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}}); + 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}}); + 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}}); + } + } + + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format FloatOp { + 0x0: movfs({{ if ( FPConditionCode(CC) == 0 ) Fd = Fs; }}); + 0x1: movts({{ if ( FPConditionCode(CC) == 1 ) Fd = Fs;}}); + } + } + + format BasicOp { + 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); + 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); + } + + format Float64Op { + 0x2: recips({{ Fd = 1 / Fs; }}); + 0x3: rsqrts({{ Fd = 1 / sqrt(Fs.ud);}}); + } + } + + 0x4: decode RS_LO { + + format FloatOp { + 0x1: cvt_d_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE); - }}); + }}); - 0x4: cvt_w_s({{ int rnd_mode = xc->miscRegs.fcsr; + 0x4: cvt_w_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE); - }}); + }}); + } - //only legal for 64 bit - format Float64Op { - 0x5: cvt_l_s({{ int rnd_mode = xc->miscRegs.fcsr; + //only legal for 64 bit + format Float64Op { + 0x5: cvt_l_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_LONG,FP_SINGLE); - }}); - - 0x6: cvt_ps_s({{ Fd.df = Fs.df<31:0> | Ft.df<31:0>; }}); - } - } - } + }}); - //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D - 0x1: decode RS_HI { - 0x0: decode RS_LO { - format FloatOp { - 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); - 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); - 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); - 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); - 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); - 0x5: absd({{ Fd.df = abs(Fs.df);}}); - 0x6: movd({{ Fd.df = Fs.df;}}); - 0x7: negd({{ Fd.df = -1 * Fs.df;}}); - } - } - - 0x1: decode RS_LO { - //only legal for 64 bit - format FloatOp64 { - 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); - 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); - 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); - 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}}); - } - - format FloatOp { - 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); - 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }}); - 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }}); - 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }}); - } - } - - 0x2: decode RS_LO { - 0x1: decode MOVCF { - format FloatOp { - 0x0: movfd({{ if (FPConditionCode(CC) == 0) Fd.df = Fs.df; }}); - 0x1: movtd({{ if (FPConditionCode(CC) == 1) Fd.df = Fs.df; }}); - } - } + 0x6: cvt_ps_s({{ Fd.df = Fs.df<31:0> | Ft.df<31:0>; }}); + } + } + } + + //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D + 0x1: decode RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); + 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); + 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); + 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); + 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); + 0x5: absd({{ Fd.df = abs(Fs.df);}}); + 0x6: movd({{ Fd.df = Fs.df;}}); + 0x7: negd({{ Fd.df = -1 * Fs.df;}}); + } + } - format BasicOp { - 0x2: movz({{ if (Rt == 0) Fd.df = Fs.df; }}); - 0x3: movn({{ if (Rt != 0) Fd.df = Fs.df; }}); - } + 0x1: decode RS_LO { + //only legal for 64 bit + format Float64Op { + 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); + 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); + 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); + 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}}); + } + + format FloatOp { + 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); + 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }}); + 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }}); + 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }}); + } + } - format FloatOp64 { - 0x5: recipd({{ Fd.df = 1 / Fs.df}}); - 0x6: rsqrtd{{ Fd.df = 1 / sqrt(Fs.df) }}); - } - } + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format FloatOp { + 0x0: movfd({{ if (FPConditionCode(CC) == 0) Fd.df = Fs.df; }}); + 0x1: movtd({{ if (FPConditionCode(CC) == 1) Fd.df = Fs.df; }}); + } + } + + format BasicOp { + 0x2: movz({{ if (Rt == 0) Fd.df = Fs.df; }}); + 0x3: movn({{ if (Rt != 0) Fd.df = Fs.df; }}); + } + + format Float64Op { + 0x5: recipd({{ Fd.df = 1 / Fs.df}}); + 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }}); + } + } - 0x4: decode RS_LO { - format FloatOp { - 0x0: cvt_s_d({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE); - }}); + 0x4: decode RS_LO { + format FloatOp { + 0x0: cvt_s_d({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE); + }}); - 0x4: cvt_w_d({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE); - }}); - } + 0x4: cvt_w_d({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE); + }}); + } - //only legal for 64 bit - format FloatOp64 { - 0x5: cvt_l_d({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); - }}); - } - } - } + //only legal for 64 bit + format Float64Op { + 0x5: cvt_l_d({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); + }}); + } + } + } - //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W - 0x4: decode FUNCTION { - format FloatOp { - 0x10: cvt_s({{ + //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W + 0x4: decode FUNCTION { + format FloatOp { + 0x10: cvt_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD); }}); - 0x10: cvt_d({{ + 0x10: cvt_d({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_WORD); }}); - } - } - - //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=L1 - //Note: "1. Format type L is legal only if 64-bit floating point operations - //are enabled." - 0x5: decode FUNCTION_HI { - format FloatOp { - 0x10: cvt_s_l({{ + } + } + + //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=L1 + //Note: "1. Format type L is legal only if 64-bit floating point operations + //are enabled." + 0x5: decode FUNCTION_HI { + format FloatOp { + 0x10: cvt_s_l({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG); }}); - 0x11: cvt_d_l({{ + 0x11: cvt_d_l({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_LONG); }}); - } - } + } + } + + //Table A-17 MIPS64 COP1 Encoding of Function Field When rs=PS1 + //Note: "1. Format type PS is legal only if 64-bit floating point operations + //are enabled. " + 0x6: decode RS_HI { + 0x0: decode RS_LO { + format Float64Op { + 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df + Ft.df; + }}); - //Table A-17 MIPS64 COP1 Encoding of Function Field When rs=PS1 - //Note: "1. Format type PS is legal only if 64-bit floating point operations - //are enabled. " - 0x6: decode RS_HI { - 0x0: decode RS_LO { - format FloatOp64 { - 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df + Ft.df; - }}); - - 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df - Ft.df; - }}); + 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df - Ft.df; + }}); - 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df * Ft.df; - }}); + 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df * Ft.df; + }}); - 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = abs(Fs.df); - }}); + 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = abs(Fs.df); + }}); - 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs<31:0> | Ft<31:0>; - }}); + 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs<31:0> | Ft<31:0>; + }}); - 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = -1 * Fs.df; - }}); - } - } + 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = -1 * Fs.df; + }}); + } + } - 0x2: decode RS_LO { - 0x1: decode MOVCF { - format FloatOp64 { - 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}) - 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}) - } - } + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format Float64Op { + 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}); + 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}); + } + } - } + } - 0x4: decode RS_LO { - 0x0: FloatOp64::cvt_s_pu({{ + 0x4: decode RS_LO { + 0x0: Float64Op::cvt_s_pu({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_PS_HI); - }}); - } + }}); + } - 0x5: decode RS_LO { - format FloatOp64 { - 0x0: cvt_s_pl({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); - }}); - 0x4: pll({{ Fd.df = Fs<31:0> | Ft<31:0>}}); - 0x5: plu({{ Fd.df = Fs<31:0> | Ft<63:32>}}); - 0x6: pul({{ Fd.df = Fs<63:32> | Ft<31:0>}}); - 0x7: puu({{ Fd.df = Fs<63:32 | Ft<63:32>}}); - } - } - } - } - - //Table A-19 MIPS32 COP2 Encoding of rs Field - 0x2: decode RS_MSB { - 0x0: decode RS_HI { - 0x0: decode RS_LO { - format WarnUnimpl { - 0x0: mfc2({{ }}); - 0x2: cfc2({{ }}); - 0x3: mfhc2({{ }}); - 0x4: mtc2({{ }}); - 0x6: ctc2({{ }}); - 0x7: mftc2({{ }}); - } - } - - 0x1: decode ND { - 0x0: decode TF { - format WarnUnimpl { - 0x0: bc2f({{ cond = (xc->miscRegs.cop2cc == 0); }}, COP2); - 0x1: bc2t({{ cond = (xc->miscRegs.cop2cc == 1); }}, COP2}}); - } + 0x5: decode RS_LO { + format Float64Op { + 0x0: cvt_s_pl({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); + }}); + 0x4: pll({{ Fd.df = Fs<31:0> | Ft<31:0>}}); + 0x5: plu({{ Fd.df = Fs<31:0> | Ft<63:32>}}); + 0x6: pul({{ Fd.df = Fs<63:32> | Ft<31:0>}}); + 0x7: puu({{ Fd.df = Fs<63:32 | Ft<63:32>}}); + } + } + } + } } + } + + //Table A-19 MIPS32 COP2 Encoding of rs Field + 0x2: decode RS_MSB { + 0x0: decode RS_HI { + 0x0: decode RS_LO { + format WarnUnimpl { + 0x0: mfc2(); + 0x2: cfc2(); + 0x3: mfhc2(); + 0x4: mtc2(); + 0x6: ctc2(); + 0x7: mftc2(); + } + } + + 0x1: decode ND { + 0x0: decode TF { + format WarnUnimpl { + 0x0: bc2f(); + 0x1: bc2t(); + } + } - 0x1: decode TF { - format WarnUnimpl { - 0x0: bc2fl({{ cond = (xc->miscRegs.cop2cc == 0); }}, COP2}}); - 0x1: bc2tl({{ cond = (xc->miscRegs.cop2cc == 1); }}, COP2}}); - } + 0x1: decode TF { + format WarnUnimpl { + 0x0: bc2fl(); + 0x1: bc2tl(); + } + } + } } - } } - } - - //Table A-20 MIPS64 COP1X Encoding of Function Field 1 - //Note: "COP1X instructions are legal only if 64-bit floating point - //operations are enabled." - 0x3: decode FUNCTION_HI { - 0x0: decode FUNCTION_LO { - format Memory { - 0x0: lwxc1({{ EA = Rs + Rt; }},{{ Ft<31:0> = Mem.uf; }}); - 0x1: ldxc1({{ EA = Rs + Rt; }},{{ Ft<63:0> = Mem.df; }}); - 0x5: luxc1({{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}, - {{ Ft<31:0> = Mem.df; }}); + + //Table A-20 MIPS64 COP1X Encoding of Function Field 1 + //Note: "COP1X instructions are legal only if 64-bit floating point + //operations are enabled." + 0x3: decode FUNCTION_HI { + 0x0: decode FUNCTION_LO { + format LoadMemory2 { + 0x0: lwxc1({{ EA = Rs + Rt; }},{{ Ft<31:0> = Mem.sf; }}); + 0x1: ldxc1({{ EA = Rs + Rt; }},{{ Ft<63:0> = Mem.df; }}); + 0x5: luxc1({{ //Need to make EA<2:0> = 0 + EA = Rs + Rt; + }}, + {{ Ft<31:0> = Mem.df; }}); } - } + } - 0x1: decode FUNCTION_LO { - format Memory { - 0x0: swxc1({{ EA = Rs + Rt; }},{{ Mem.uf = Ft<31:0>; }}); - 0x1: sdxc1({{ EA = Rs + Rt; }},{{ Mem.uf = Ft<63:0>}}); - 0x5: suxc1({{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}, - {{ Mem.df = Ft<63:0>;}}); - 0x7: prefx({{ }}); + 0x1: decode FUNCTION_LO { + format StoreMemory2 { + 0x0: swxc1({{ EA = Rs + Rt; }},{{ Mem.sf = Ft<31:0>; }}); + 0x1: sdxc1({{ EA = Rs + Rt; }},{{ Mem.df = Ft<63:0>}}); + 0x5: suxc1({{ //Need to make EA<2:0> = 0 + EA = Rs + Rt; + }}, + {{ Mem.df = Ft<63:0>;}}); } - } - format FloatOp { - 0x3: WarnUnimpl::alnv_ps({{ }}); + 0x7: WarnUnimpl::prefx(); + } + + format FloatOp { + 0x3: WarnUnimpl::alnv_ps(); format BasicOp { - 0x4: decode FUNCTION_LO { - 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); - 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); - 0x6: madd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) + Fr.df; - }}); - } - - 0x5: decode FUNCTION_LO { - 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); - 0x6: msub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) - Fr.df; - }}); - } - - 0x6: decode FUNCTION_LO { - 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); - 0x6: nmadd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; - }}); - } - - 0x7: decode FUNCTION_LO { - 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); - 0x6: nmsub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; - }}); - } + 0x4: decode FUNCTION_LO { + 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); + 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); + 0x6: madd_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (Fs.df * Fs.df) + Fr.df; + }}); + } + + 0x5: decode FUNCTION_LO { + 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); + 0x6: msub_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (Fs.df * Fs.df) - Fr.df; + }}); + } + + 0x6: decode FUNCTION_LO { + 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); + 0x6: nmadd_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + }}); + } + + 0x7: decode FUNCTION_LO { + 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); + 0x6: nmsub_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + }}); + } } + } } - } - //MIPS obsolete instructions - format Branch { - 0x4: beql({{ cond = (Rs.sq == 0); }}); - 0x5: bnel({{ cond = (Rs.sq != 0); }}); - 0x6: blezl({{ cond = (Rs.sq <= 0); }}); - 0x7: bgtzl({{ cond = (Rs.sq > 0); }}); + //MIPS obsolete instructions + format BranchLikely { + 0x4: beql({{ cond = (Rs.sw == 0); }}); + 0x5: bnel({{ cond = (Rs.sw != 0); }}); + 0x6: blezl({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtzl({{ cond = (Rs.sw > 0); }}); } - }; + } 0x3: decode OPCODE_LO default FailUnimpl::reserved() { @@ -747,149 +762,149 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x0: decode FUNCTION_LO { format IntOp { - 0x0: madd({{ + 0x0: madd({{ INT64 temp1 = Hi.sw << 32 | Lo.sw >> 32; temp1 = temp1 + (Rs.sw * Rt.sw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); - 0x1: maddu({{ + 0x1: maddu({{ INT64 temp1 = Hi.uw << 32 | Lo.uw >> 32; temp1 = temp1 + (Rs.uw * Rt.uw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); - 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); + 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); - 0x4: msub({{ + 0x4: msub({{ INT64 temp1 = Hi.sw << 32 | Lo.sw >> 32; temp1 = temp1 - (Rs.sw * Rt.sw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); - 0x5: msubu({{ + 0x5: msubu({{ INT64 temp1 = Hi.uw << 32 | Lo.uw >> 32; temp1 = temp1 - (Rs.uw * Rt.uw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); } } 0x4: decode FUNCTION_LO { - format BasicOp { - 0x0: clz({{ + format BasicOp { + 0x0: clz({{ int cnt = 0; int idx = 0; while ( Rs.uw<idx>!= 1) { - cnt++; - idx--; + cnt++; + idx--; } Rd.uw = cnt; - }}); + }}); - 0x1: clo({{ + 0x1: clo({{ int cnt = 0; int idx = 0; while ( Rs.uw<idx>!= 0) { - cnt++; - idx--; + cnt++; + idx--; } Rd.uw = cnt; - }}); - } + }}); + } } 0x7: decode FUNCTION_LO { - 0x7: WarnUnimpl::sdbbp({{ }}); + 0x7: WarnUnimpl::sdbbp(); } } //Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 of the Architecture 0x7: decode FUNCTION_HI { - 0x0: decode FUNCTION_LO { + 0x0: decode FUNCTION_LO { format WarnUnimpl { - 0x1: ext({{ }}); - 0x4: ins({{ }}); + 0x1: ext(); + 0x4: ins(); } - } + } - 0x1: decode FUNCTION_LO { + 0x1: decode FUNCTION_LO { format WarnUnimpl { - 0x0: fork({{ }}); - 0x1: yield({{ }}); + 0x0: fork(); + 0x1: yield(); } - } + } - //Table A-10 MIPS32 BSHFL Encoding of sa Field - 0x4: decode SA { + //Table A-10 MIPS32 BSHFL Encoding of sa Field + 0x4: decode SA { - 0x02: WarnUnimpl::wsbh({{ }}); + 0x02: WarnUnimpl::wsbh(); format BasicOp { 0x10: seb({{ Rd.sw = /* sext32(Rt<7>,24) | */ Rt<7:0>}}); 0x18: seh({{ Rd.sw = /* sext32(Rt<15>,16) | */ Rt<15:0>}}); } - } + } - 0x6: decode FUNCTION_LO { - 0x7: BasicOp::rdhwr({{ Rt = xc->hwRegs[RD];}}); - } + 0x6: decode FUNCTION_LO { + 0x7: BasicOp::rdhwr({{ Rt = xc->hwRegs[RD];}}); + } } - }; + } 0x4: decode OPCODE_LO default FailUnimpl::reserved() { - format Memory { - 0x0: lb({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sb; }}); - 0x1: lh({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sh; }}); - 0x2: lwl({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sw; }}, WordAlign); - 0x3: lw({{ EA = Rs + disp; }}, {{ Rb.uq = Mem.sb; }}); - 0x4: lbu({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.ub; }}); - 0x5: lhu({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uh; }}); - 0x6: lwr({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uw; }}, WordAlign); - }; - - 0x7: FailUnimpl::reserved({{ }}); - }; + format LoadMemory { + 0x0: lb({{ Rb.sw = Mem.sb; }}); + 0x1: lh({{ Rb.sw = Mem.sh; }}); + 0x2: lwl({{ Rb.sw = Mem.sw; }});//, WordAlign); + 0x3: lw({{ Rb.uq = Mem.sb; }}); + 0x4: lbu({{ Rb.uw = Mem.ub; }}); + 0x5: lhu({{ Rb.uw = Mem.uh; }}); + 0x6: lwr({{ Rb.uw = Mem.uw; }});//, WordAlign); + } + + 0x7: FailUnimpl::reserved(); + } 0x5: decode OPCODE_LO default FailUnimpl::reserved() { - format Memory { - 0x0: sb({{ EA = Rs + disp; }}, {{ Mem.ub = Rt<7:0>; }}); - 0x1: sh({{ EA = Rs + disp; }},{{ Mem.uh = Rt<15:0>; }}); - 0x2: swl({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }},WordAlign); - 0x3: sw({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }}); - 0x6: swr({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }},WordAlign); - }; + format StoreMemory { + 0x0: sb({{ Mem.ub = Rt<7:0>; }}); + 0x1: sh({{ Mem.uh = Rt<15:0>; }}); + 0x2: swl({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + 0x3: sw({{ Mem.ub = Rt<31:0>; }}); + 0x6: swr({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + } format WarnUnimpl { - 0x7: cache({{ }}); - }; + 0x7: cache(); + } - }; + } 0x6: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::ll({{ }}); + 0x0: WarnUnimpl::ll(); - format Memory { - 0x1: lwc1({{ EA = Rs + disp; }},{{ Ft<31:0> = Mem.uf; }}); - 0x5: ldc1({{ EA = Rs + disp; }},{{ Ft<63:0> = Mem.df; }}); - }; - }; + format LoadMemory { + 0x1: lwc1({{ Ft<31:0> = Mem.sf; }}); + 0x5: ldc1({{ Ft<63:0> = Mem.df; }}); + } + } 0x7: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::sc({{ }}); + 0x0: WarnUnimpl::sc(); - format Memory { - 0x1: swc1({{ EA = Rs + disp; }},{{ Mem.uf = Ft<31:0>; }}); - 0x5: sdc1({{ EA = Rs + disp; }},{{ Mem.df = Ft<63:0>; }}); - }; + format StoreMemory { + 0x1: swc1({{ Mem.sf = Ft<31:0>; }}); + 0x5: sdc1({{ Mem.df = Ft<63:0>; }}); + } } } diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa index 404314c7a..c244013df 100644 --- a/arch/mips/isa/formats.isa +++ b/arch/mips/isa/formats.isa @@ -1,22 +1,33 @@ -//Include the basic format +// -*- mode:c++ -*- + //Templates from this format are used later -##include "m5/arch/mips/isa_desc/formats/basic.format" +//Include the basic format +##include "m5/arch/mips/isa/formats/basic.isa" + +//Include the basic format +##include "m5/arch/mips/isa/formats/noop.isa" + +//Include utility formats/functions +##include "m5/arch/mips/isa/formats/util.isa" //Include the integerOp and integerOpCc format -##include "m5/arch/mips/isa_desc/formats/integerop.format" +##include "m5/arch/mips/isa/formats/int.isa" //Include the floatOp format -##include "m5/arch/mips/isa_desc/formats/floatop.format" +##include "m5/arch/mips/isa/formats/fp.isa" //Include the mem format -##include "m5/arch/mips/isa_desc/formats/mem.format" +##include "m5/arch/mips/isa/formats/mem.isa" //Include the trap format -##include "m5/arch/mips/isa_desc/formats/trap.format" +##include "m5/arch/mips/isa/formats/trap.isa" //Include the branch format -##include "m5/arch/mips/isa_desc/formats/branch.format" +##include "m5/arch/mips/isa/formats/branch.isa" + +//Include the noop format +##include "m5/arch/mips/isa/formats/unimp.isa" //Include the noop format -##include "m5/arch/mips/isa_desc/formats/noop.format" +##include "m5/arch/mips/isa/formats/unknown.isa" diff --git a/arch/mips/isa/formats/basic.isa b/arch/mips/isa/formats/basic.isa index 8fba9845a..3b62aa5c3 100644 --- a/arch/mips/isa/formats/basic.isa +++ b/arch/mips/isa/formats/basic.isa @@ -1,3 +1,4 @@ +// -*- mode:c++ -*- // Declarations for execute() methods. def template BasicExecDeclare {{ @@ -39,7 +40,7 @@ def template BasicExecute {{ if(fault == No_Fault) { - %(op_wb)s; + %(op_wb)s; } return fault; } @@ -56,7 +57,7 @@ def template BasicDecodeWithMnemonic {{ }}; // The most basic instruction format... used only for a few misc. insts -def format BasicOperate(code, *flags) {{ +def format BasicOp(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/arch/mips/isa/formats/branch.isa b/arch/mips/isa/formats/branch.isa index a565eb71b..fc207fd3f 100644 --- a/arch/mips/isa/formats/branch.isa +++ b/arch/mips/isa/formats/branch.isa @@ -1,66 +1,317 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // -// Branch instructions +// Control transfer instructions // output header {{ - /** - * Base class for integer operations. - */ - class Branch : public MipsStaticInst + + /** + * 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 MipsStaticInst + { + 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, MachInst _machInst, + OpClass __opClass) + : MipsStaticInst(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) { - protected: + } - /// Constructor - Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; -}}; + /** + * Base class for branches (PC-relative control transfers), + * conditional or unconditional. + */ + class Branch : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; -output decoder {{ - std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) { - return "Disassembly of integer instruction\n"; } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branch likely branches (PC-relative control transfers), + */ + class BranchLikely : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; + + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for jumps (register-indirect control transfers). In + * the Mips ISA, these are always unconditional. + */ + class Jump : public PCDependentDisassembly + { + protected: + + /// Displacement to target address (signed). + int32_t disp; + + public: + /// Constructor + Jump(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET) + { + } + + Addr branchTarget(ExecContext *xc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; }}; -def template BranchExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const +output decoder {{ + Addr + Branch::branchTarget(Addr branchPC) const + { + return branchPC + 4 + disp; + } + + Addr + BranchLikely::branchTarget(Addr branchPC) const + { + return branchPC + 4 + disp; + } + + Addr + Jump::branchTarget(ExecContext *xc) const + { + Addr NPC = xc->readPC() + 4; + uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); + return (Rb & ~3) | (NPC & 1); + } + + const std::string & + PCDependentDisassembly::disassemble(Addr pc, + const SymbolTable *symtab) const + { + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) { - //Attempt to execute the instruction - try - { - checkPriv; - - %(op_decl)s; - %(op_rd)s; - %(code)s; - } - //If we have an exception for some reason, - //deal with it - catch(MipsException except) - { - //Deal with exception - return No_Fault; - } - - //Write the resulting state to the execution context - %(op_wb)s; - - return No_Fault; + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; + } + + std::string + Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + else if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numSrcRegs == 0 && _numDestRegs == 0) { + printReg(ss, 31); + ss << ","; + } +#endif + + Addr target = pc + 4 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + else if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numSrcRegs == 0 && _numDestRegs == 0) { + printReg(ss, 31); + ss << ","; + } +#endif + + Addr target = pc + 4 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numDestRegs == 0) { + printReg(ss, 31); + ss << ","; } +#endif + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + + ccprintf(ss, "(r%d)", RB); + + return ss.str(); + } }}; -def format CondBranch(code) {{ - code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; +def format Branch(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if name[strlen-2:] == 'al': + code += 'R31 = NNPC;\n' + + #Condition code + code = 'bool cond;\n' + code + code += 'if (cond) {\n' + #code += '//NPC=NPC: just placeholder to force parser to writeback NPC\n' + #code += ' NPC = NPC; \n' + code += ' NNPC = NPC + disp;\n' + code += '} \n' + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), ('IsDirectControl', 'IsCondControl')) + header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; + +def format BranchLikely(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if name[strlen-3:] == 'all': + code += 'R31 = NNPC;\n' + + #Condition code + code = 'bool cond;\n' + code + code += 'if (cond) {' + #code += '//NPC=NPC: just placeholder to force parser to writeback NPC\n' + #code += 'NPC = NPC; \n' + code += 'NNPC = NPC + disp;\n' + code += '} \n' + + + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), + ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format Jump(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if strlen >= 3 and name[2:3] == 'al': + code = 'R31 = NNPC;\n' + code + + iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ + ('IsIndirectControl', 'IsUncondControl')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + + + diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa index 707109fc2..23fcbaa67 100644 --- a/arch/mips/isa/formats/fp.isa +++ b/arch/mips/isa/formats/fp.isa @@ -27,7 +27,7 @@ output decoder {{ } }}; -def template FPExecute {{ +def template FloatingPointExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { //These are set to constants when the execute method @@ -70,7 +70,7 @@ def template FPExecute {{ }}; // Primary format for integer operate instructions: -def format FPOp(code, *opt_flags) {{ +def format FloatOp(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) checkPriv = (code.find('checkPriv') != -1) @@ -86,12 +86,33 @@ def format FPOp(code, *opt_flags) {{ header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = IntegerExecute.subst(iop) + exec_output = FloatingPointExecute.subst(iop) +}}; + +// Primary format for integer operate instructions: +def format Float64Op(code, *opt_flags) {{ + orig_code = code + cblk = CodeBlock(code) + checkPriv = (code.find('checkPriv') != -1) + code.replace('checkPriv', '') + if checkPriv: + code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;') + else: + code.replace('checkPriv;', '') + for (marker, value) in (('ivValue', '0'), ('icValue', '0'), + ('xvValue', '0'), ('xcValue', '0')): + code.replace(marker, value) + iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecodeWithMnemonic.subst(iop) + exec_output = FloatingPointExecute.subst(iop) }}; // Primary format for integer operate instructions: def format FPOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{ orig_code = code + cblk = CodeBlock(code) checkPriv = (code.find('checkPriv') != -1) code.replace('checkPriv', '') diff --git a/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa index 5b8df54e9..cf06741a1 100644 --- a/arch/mips/isa/formats/int.isa +++ b/arch/mips/isa/formats/int.isa @@ -1,8 +1,11 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // // Integer operate instructions // +//Outputs to decoder.hh output header {{ /** * Base class for integer operations. @@ -12,7 +15,7 @@ output header {{ protected: /// Constructor - IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) { } @@ -26,7 +29,7 @@ output header {{ uint16_t imm; /// Constructor - IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM) { } @@ -36,6 +39,7 @@ output header {{ }}; +//Outputs to decoder.cc output decoder {{ std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { @@ -48,17 +52,18 @@ output decoder {{ } }}; -// Primary format for integer operate instructions: + +//Used by decoder.isa def format IntOp(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) - //Figure out if we are creating a IntImmOp or a IntOp + # Figure out if we are creating a IntImmOp or a IntOp + # by looking at the instruction name + iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) strlen = len(name) - if ( name[strlen-1] = 'i' or ( name[strlen-2:] = 'iu')) - iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) - else: - iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) + if name[strlen-1] == 'i' or name[strlen-2:] == 'iu': + iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa index 5ed5237c5..134548746 100644 --- a/arch/mips/isa/formats/mem.isa +++ b/arch/mips/isa/formats/mem.isa @@ -1,78 +1,462 @@ -//////////////////////////////////////////////////////////////////// +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. // -// Mem instructions +// 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. output header {{ + /** + * Base class for general Mips memory-format instructions. + */ + class Memory : public MipsStaticInst + { + protected: + + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + /// Displacement for EA calculation (signed). + int32_t disp; + + /// Constructor + Memory(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : MipsStaticInst(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + disp(OFFSET) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + public: + + const StaticInstPtr &eaCompInst() const { return eaCompPtr; } + const StaticInstPtr &memAccInst() const { return memAccPtr; } + }; + +}}; + + +output decoder {{ + std::string + Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s %c%d,%d(r%d)", mnemonic, + flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB); + } + +}}; + +def format LoadAddress(code) {{ + iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + protected: + /** - * Base class for integer operations. + * "Fake" effective address computation class for "%(mnemonic)s". */ - class Mem : public MipsStaticInst + class EAComp : public %(base_class)s { - protected: + public: + /// Constructor + EAComp(MachInst machInst); - /// Constructor - Mem(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + %(BasicExecDeclare)s + }; - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + /** + * "Fake" memory access instruction class for "%(mnemonic)s". + */ + class MemAcc : public %(base_class)s + { + public: + /// Constructor + MemAcc(MachInst machInst); + + %(BasicExecDeclare)s }; + + public: + + /// Constructor. + %(class_name)s(MachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; }}; -output decoder {{ - std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const - { - return "Disassembly of integer instruction\n"; + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template LoadStoreConstructor {{ + /** TODO: change op_class to AddrGenOp or something (requires + * creating new member of OpClass enum in op_class.hh, updating + * config files, etc.). */ + inline %(class_name)s::EAComp::EAComp(MachInst machInst) + : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) + { + %(ea_constructor)s; + } + + inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) + : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) + { + %(memacc_constructor)s; + } + + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + new EAComp(machInst), new MemAcc(machInst)) + { + %(constructor)s; + } +}}; + + +def template EACompExecute {{ + Fault + %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) { + %(op_wb)s; + xc->setEA(EA); } + + return fault; + } }}; -def template MemExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - //Attempt to execute the instruction - try - { - - %(op_decl)s; - %(op_rd)s; - ea_code - %(code)s; - } - //If we have an exception for some reason, - //deal with it - catch(MipsException except) - { - //Deal with exception - return No_Fault; - } - - //Write the resulting state to the execution context - %(op_wb)s; - - return No_Fault; - } -}}; - -// Primary format for integer operate instructions: -def format Mem(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = MemExecute.subst(iop) - exec_output.replace('ea_code', 'EA = I ? (R1 + SIMM13) : R1 + R2;'); -}}; - -def format Cas(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = MemExecute.subst(iop) - exec_output.replace('ea_code', 'EA = R1;'); +def template LoadMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } }}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + + memcpy(&Mem, data, sizeof(Mem)); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + %(code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&write_result, data, sizeof(write_result)); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +// load instructions use Rt as dest, so check for +// Rt == 31 to detect nops +def template LoadNopCheckDecode {{ + { + MipsStaticInst *i = new %(class_name)s(machInst); + if (RT == 0) { + i = makeNop(i); + } + return i; + } +}}; + +def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + +//FP loads are offloaded to these formats for now ... +def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +//FP stores are offloaded to these formats for now ... +def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Store') +}}; + diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa index b1ece654d..d366461e2 100644 --- a/arch/mips/isa/formats/noop.isa +++ b/arch/mips/isa/formats/noop.isa @@ -1,47 +1,88 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // -// Noop instruction +// Nop // output header {{ - /** - * Base class for integer operations. - */ - class Noop : public MipsStaticInst + /** + * Static instruction class for no-ops. This is a leaf class. + */ + class Nop : public MipsStaticInst + { + /// Disassembly of original instruction. + const std::string originalDisassembly; + + public: + /// Constructor + Nop(const std::string _originalDisassembly, MachInst _machInst) + : MipsStaticInst("nop", _machInst, No_OpClass), + originalDisassembly(_originalDisassembly) { - protected: + flags[IsNop] = true; + } + + ~Nop() { } - /// Constructor - Noop(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; + %(BasicExecDeclare)s + }; }}; output decoder {{ - std::string Noop::generateDisassembly(Addr pc, const SymbolTable *symtab) const - { - return "Disassembly of integer instruction\n"; - } + std::string Nop::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return originalDisassembly; +#else + return csprintf("%-10s (%s)", "nop", originalDisassembly); +#endif + } + + /// Helper function for decoding nops. Substitute Nop object + /// for original inst passed in as arg (and delete latter). + inline + MipsStaticInst * + makeNop(MipsStaticInst *inst) + { + MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); + delete inst; + return nop; + } }}; -def template NoopExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - //Nothing to see here, move along - return No_Fault; - } +output exec {{ + Fault + Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + return No_Fault; + } +}}; + +// integer & FP operate instructions use Rc as dest, so check for +// Rc == 31 to detect nops +def template OperateNopCheckDecode {{ + { + MipsStaticInst *i = new %(class_name)s(machInst); + if (RC == 31) { + i = makeNop(i); + } + return i; + } }}; -// Primary format for integer operate instructions: -def format Noop(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = NoopExecute.subst(iop) + +// Like BasicOperate format, but generates NOP if RC/FC == 31 +def format BasicOperateWithNopCheck(code, *opt_args) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), + opt_args) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) }}; + diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa new file mode 100644 index 000000000..a7a71c681 --- /dev/null +++ b/arch/mips/isa/formats/unimp.isa @@ -0,0 +1,165 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public MipsStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, MachInst _machInst) + : MipsStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public MipsStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s", mnemonic); +#else + return csprintf("%-10s (unimplemented)", mnemonic); +#endif + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE); + return Unimplemented_Opcode_Fault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("instruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return No_Fault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public MipsStaticInst + { + public: + /// Constructor + Unknown(MachInst _machInst) + : MipsStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa new file mode 100644 index 000000000..6eba5b4f9 --- /dev/null +++ b/arch/mips/isa/formats/unknown.isa @@ -0,0 +1,52 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x)", + "unknown", machInst, OPCODE); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction " + "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); + return Unimplemented_Opcode_Fault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa new file mode 100644 index 000000000..f0671726c --- /dev/null +++ b/arch/mips/isa/formats/util.isa @@ -0,0 +1,125 @@ +// -*- mode:c++ -*- + +let {{ +def UncondCtrlBase(name, Name, base_class, npc_expr, flags): + # Declare basic control transfer w/o link (i.e. link reg is R31) + nolink_code = 'NPC = %s;\n' % npc_expr + nolink_iop = InstObjParams(name, Name, base_class, + CodeBlock(nolink_code), flags) + header_output = BasicDeclare.subst(nolink_iop) + decoder_output = BasicConstructor.subst(nolink_iop) + exec_output = BasicExecute.subst(nolink_iop) + + # Generate declaration of '*AndLink' version, append to decls + link_code = 'Ra = NPC & ~3;\n' + nolink_code + link_iop = InstObjParams(name, Name + 'AndLink', base_class, + CodeBlock(link_code), flags) + header_output += BasicDeclare.subst(link_iop) + decoder_output += BasicConstructor.subst(link_iop) + exec_output += BasicExecute.subst(link_iop) + + # need to use link_iop for the decode template since it is expecting + # the shorter version of class_name (w/o "AndLink") + + return (header_output, decoder_output, + JumpOrBranchDecode.subst(nolink_iop), exec_output) + +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code = '', base_class = 'Memory', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # add hook to get effective addresses into execution trace output. + ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' + + # generate code block objects + ea_cblk = CodeBlock(ea_code) + memacc_cblk = CodeBlock(memacc_code) + postacc_cblk = CodeBlock(postacc_code) + + # Some CPU models execute the memory operation as an atomic unit, + # while others want to separate them into an effective address + # computation and a memory access operation. As a result, we need + # to generate three StaticInst objects. Note that the latter two + # are nested inside the larger "atomic" one. + + # generate InstObjParams for EAComp object + ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags) + + # generate InstObjParams for MemAcc object + memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags) + # in the split execution model, the MemAcc portion is responsible + # for the post-access code. + memacc_iop.postacc_code = postacc_cblk.code + + # generate InstObjParams for InitiateAcc, CompleteAcc object + # The code used depends on the template being used + if (exec_template_base == 'Load'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(memacc_code + postacc_code) + elif (exec_template_base == 'Store'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(postacc_code) + else: + initiateacc_cblk = '' + completeacc_cblk = '' + + initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk, + inst_flags) + + completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk, + inst_flags) + + if (exec_template_base == 'Load'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + elif (exec_template_base == 'Store'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + + # generate InstObjParams for unified execution + cblk = CodeBlock(ea_code + memacc_code + postacc_code) + iop = InstObjParams(name, Name, base_class, cblk, inst_flags) + + iop.ea_constructor = ea_cblk.constructor + iop.ea_code = ea_cblk.code + iop.memacc_constructor = memacc_cblk.constructor + iop.memacc_code = memacc_cblk.code + iop.postacc_code = postacc_cblk.code + + if mem_flags: + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + memacc_iop.constructor += s + + # select templates + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + EACompExecute.subst(ea_iop) + + memAccExecTemplate.subst(memacc_iop) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(initiateacc_iop) + + completeAccTemplate.subst(completeacc_iop)) +}}; + + +output exec {{ + + /// CLEAR ALL CPU INST/EXE HAZARDS + inline void + clear_exe_inst_hazards() + { + //CODE HERE + } +} diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa index a8c71872b..411e398b4 100644 --- a/arch/mips/isa/main.isa +++ b/arch/mips/isa/main.isa @@ -26,7 +26,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. -##include "m5/arch/sparc/isa_desc/includes.h" +##include "m5/arch/mips/isa/includes.isa" //////////////////////////////////////////////////////////////////// // @@ -37,16 +37,16 @@ namespace MipsISA; //Include the bitfield definitions -##include "m5/arch/mips/isa_desc/bitfields.h" +##include "m5/arch/mips/isa/bitfields.isa" //Include the operand_types and operand definitions -##include "m5/arch/mips/isa_desc/operands.h" +##include "m5/arch/mips/isa/operands.isa" //Include the base class for mips instructions, and some support code -##include "m5/arch/mips/isa_desc/base.h" +##include "m5/arch/mips/isa/base.isa" //Include the definitions for the instruction formats -##include "m5/arch/mips/isa_desc/formats.h" +##include "m5/arch/mips/isa/formats.isa" //Include the decoder definition -##include "m5/arch/mips/isa_desc/decoder.h" +##include "m5/arch/mips/isa/decoder.isa" diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa index c8e08a436..65ef2245f 100644 --- a/arch/mips/isa/operands.isa +++ b/arch/mips/isa/operands.isa @@ -1,12 +1,12 @@ def operand_types {{ 'sb' : ('signed int', 8), 'ub' : ('unsigned int', 8), - 'shw' : ('signed int', 16), - 'uhw' : ('unsigned int', 16), + 'sh' : ('signed int', 16), + 'uh' : ('unsigned int', 16), 'sw' : ('signed int', 32), 'uw' : ('unsigned int', 32), - 'sdw' : ('signed int', 64), - 'udw' : ('unsigned int', 64), + 'sd' : ('signed int', 64), + 'ud' : ('unsigned int', 64), 'sf' : ('float', 32), 'df' : ('float', 64), 'qf' : ('float', 128) @@ -16,6 +16,7 @@ def operands {{ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1), 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2), 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3), + 'R31': ('IntReg', 'uw','R31','IsInteger', 4), 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), 'Sa': ('IntReg', 'uw', 'SA', 'IsInteger', 4), @@ -24,12 +25,12 @@ def operands {{ 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2), 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4) + 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), - #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), + 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4), + 'NNPC': ('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4) #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), # The next two are hacks for non-full-system call-pal emulation #'R0': ('IntReg', 'uq', '0', None, 1), - #'R16': ('IntReg', 'uq', '16', None, 1) }}; diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh index 55e9c0dcb..603af60e2 100644 --- a/arch/mips/isa_traits.hh +++ b/arch/mips/isa_traits.hh @@ -46,7 +46,7 @@ class Checkpoint; template <class ISA> class StaticInst; template <class ISA> class StaticInstPtr; -//namespace EV5 +//namespace MIPS34K //{ // int DTB_ASN_ASN(uint64_t reg); // int ITB_ASN_ASN(uint64_t reg); @@ -430,12 +430,14 @@ class MipsISA Addr pc; // Program Counter Addr npc; // Next Program Counter + Addr nnpc; // Next next program Counter + void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); }; - static StaticInstPtr<AlphaISA> decodeInst(MachInst); + static StaticInstPtr<MipsISA> decodeInst(MachInst); // return a no-op instruction... used for instruction fetch faults static const MachInst NoopMachInst; @@ -526,7 +528,7 @@ class SyscallReturn { #ifdef FULL_SYSTEM -#include "arch/alpha/ev5.hh" +#include "arch/mips/mips34k.hh" #endif #endif // __ARCH_MIPS_ISA_TRAITS_HH__ diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript new file mode 100644 index 000000000..fea31fd5d --- /dev/null +++ b/arch/sparc/SConscript @@ -0,0 +1,82 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import sys +from os.path import isdir + +# Import build environment variable from SConstruct. +Import('env') + +################################################### +# +# Define needed sources. +# +################################################### + +# Base sources used by all configurations. +base_sources = Split(''' + faults.cc + isa_traits.cc + ''') + +# Full-system sources +full_system_sources = Split(''' + alpha_memory.cc + arguments.cc + ev5.cc + osfpal.cc + stacktrace.cc + vtophys.cc + ''') + +# Syscall emulation (non-full-system) sources +syscall_emulation_sources = Split(''' + alpha_common_syscall_emul.cc + alpha_linux_process.cc + alpha_tru64_process.cc + ''') + +sources = base_sources + +if env['FULL_SYSTEM']: + sources += full_system_sources +else: + sources += syscall_emulation_sources + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +# Add in files generated by the ISA description. +isa_desc_files = env.ISADesc('isa/main.isa') +# Only non-header files need to be compiled. +isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] +sources += isa_desc_sources + +Return('sources') diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc index 67d745d43..17ec21fed 100644 --- a/base/remote_gdb.cc +++ b/base/remote_gdb.cc @@ -132,6 +132,7 @@ #include "targetarch/vtophys.hh" using namespace std; +using namespace TheISA; #ifndef NDEBUG vector<RemoteGDB *> debuggers; @@ -494,7 +495,7 @@ RemoteGDB::setSingleStep() // User was stopped at pc, e.g. the instruction at pc was not // executed. MachInst inst = read<MachInst>(pc); - StaticInstPtr<TheISA> si(inst); + StaticInstPtr si(inst); if (si->hasBranchTarget(pc, context, bpc)) { // Don't bother setting a breakpoint on the taken branch if it // is the same as the next pc diff --git a/base/remote_gdb.hh b/base/remote_gdb.hh index 652a58317..b7abf5116 100644 --- a/base/remote_gdb.hh +++ b/base/remote_gdb.hh @@ -43,6 +43,8 @@ class PhysicalMemory; class GDBListener; class RemoteGDB { + protected: + typedef TheISA::MachInst MachInst; private: friend void debugger(); friend class GDBListener; diff --git a/build/SConstruct b/build/SConstruct index c552e5639..38d404846 100644 --- a/build/SConstruct +++ b/build/SConstruct @@ -218,12 +218,15 @@ if have_mysql: env = conf.Finish() +# Define the universe of supported ISAs +env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips'] + # Sticky options get saved in the options file so they persist from # one invocation to the next (unless overridden, in which case the new # value becomes sticky). sticky_opts = Options(args=ARGUMENTS) sticky_opts.AddOptions( - EnumOption('TARGET_ISA', 'Target ISA', 'alpha', ('alpha', 'sparc', 'mips')), + EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']), BoolOption('FULL_SYSTEM', 'Full-system support', False), BoolOption('ALPHA_TLASER', 'Model Alpha TurboLaser platform (vs. Tsunami)', False), diff --git a/build/build_options/default/MIPS_SE b/build/build_options/default/MIPS_SE new file mode 100644 index 000000000..e74e2f69c --- /dev/null +++ b/build/build_options/default/MIPS_SE @@ -0,0 +1,2 @@ +TARGET_ISA = 'mips' +FULL_SYSTEM = 0 diff --git a/cpu/base.cc b/cpu/base.cc index 8b94b8533..5a7ecf152 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -250,7 +250,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) } #if FULL_SYSTEM - for (int i = 0; i < NumInterruptLevels; ++i) + for (int i = 0; i < TheISA::NumInterruptLevels; ++i) interrupts[i] = oldCPU->interrupts[i]; intstatus = oldCPU->intstatus; @@ -285,7 +285,7 @@ BaseCPU::post_interrupt(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); - if (int_num < 0 || int_num >= NumInterruptLevels) + if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) panic("int_num out of bounds\n"); if (index < 0 || index >= sizeof(uint64_t) * 8) @@ -301,7 +301,7 @@ BaseCPU::clear_interrupt(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - if (int_num < 0 || int_num >= NumInterruptLevels) + if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) panic("int_num out of bounds\n"); if (index < 0 || index >= sizeof(uint64_t) * 8) @@ -325,14 +325,14 @@ BaseCPU::clear_interrupts() void BaseCPU::serialize(std::ostream &os) { - SERIALIZE_ARRAY(interrupts, NumInterruptLevels); + SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); SERIALIZE_SCALAR(intstatus); } void BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); + UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); UNSERIALIZE_SCALAR(intstatus); } diff --git a/cpu/base.hh b/cpu/base.hh index 2bd1210d8..d5764d495 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -58,7 +58,7 @@ class BaseCPU : public SimObject #if FULL_SYSTEM protected: - uint64_t interrupts[NumInterruptLevels]; + uint64_t interrupts[TheISA::NumInterruptLevels]; uint64_t intstatus; public: @@ -68,7 +68,7 @@ class BaseCPU : public SimObject bool checkInterrupts; bool check_interrupt(int int_num) const { - if (int_num > NumInterruptLevels) + if (int_num > TheISA::NumInterruptLevels) panic("int_num out of bounds\n"); return interrupts[int_num] != 0; @@ -140,6 +140,8 @@ class BaseCPU : public SimObject virtual void startup(); virtual void regStats(); + virtual void activateWhenReady(int tid) {}; + void registerExecContexts(); /// Prepare for another CPU to take over execution. When it is diff --git a/cpu/base_dyn_inst.cc b/cpu/base_dyn_inst.cc index d921bd148..86314bef1 100644 --- a/cpu/base_dyn_inst.cc +++ b/cpu/base_dyn_inst.cc @@ -79,7 +79,7 @@ BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC, } template <class Impl> -BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst) +BaseDynInst<Impl>::BaseDynInst(StaticInstPtr &_staticInst) : staticInst(_staticInst), traceData(NULL) { initVars(); @@ -113,7 +113,7 @@ BaseDynInst<Impl>::initVars() asid = 0; // Initialize the fault to be unimplemented opcode. - fault = Unimplemented_Opcode_Fault; + fault = UnimplementedOpcodeFault; ++instcount; @@ -142,12 +142,12 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags) req->asid = asid; // Prefetches never cause faults. - fault = No_Fault; + fault = NoFault; // note this is a local, not BaseDynInst::fault Fault trans_fault = xc->translateDataReadReq(req); - if (trans_fault == No_Fault && !(req->flags & UNCACHEABLE)) { + if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) { // It's a valid address to cacheable space. Record key MemReq // parameters so we can generate another one just like it for // the timing access without calling translate() again (which @@ -188,7 +188,7 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags) fault = xc->translateDataWriteReq(req); - if (fault == No_Fault && !(req->flags & UNCACHEABLE)) { + if (fault == NoFault && !(req->flags & UNCACHEABLE)) { // Record key MemReq parameters so we can generate another one // just like it for the timing access without calling translate() // again (which might mess up the TLB). @@ -217,7 +217,7 @@ BaseDynInst<Impl>::copySrcTranslate(Addr src) // translate to physical address Fault fault = xc->translateDataReadReq(req); - if (fault == No_Fault) { + if (fault == NoFault) { xc->copySrcAddr = src; xc->copySrcPhysAddr = req->paddr; } else { @@ -243,7 +243,7 @@ BaseDynInst<Impl>::copy(Addr dest) // translate to physical address Fault fault = xc->translateDataWriteReq(req); - if (fault == No_Fault) { + if (fault == NoFault) { Addr dest_addr = req->paddr; // Need to read straight from memory since we have more than 8 bytes. req->paddr = xc->copySrcPhysAddr; @@ -292,7 +292,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) #if 0 panic("unaligned access. Cycle = %n", curTick); #endif - return No_Fault; + return NoFault; } MemReqPtr req = new MemReq(addr, thread, nbytes); @@ -303,7 +303,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) case Write: fault = spec_mem->write(req, (uint8_t *)p); - if (fault != No_Fault) + if (fault != NoFault) break; specMemWrite = true; @@ -325,7 +325,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) break; default: - fault = Machine_Check_Fault; + fault = MachineCheckFault; break; } diff --git a/cpu/base_dyn_inst.hh b/cpu/base_dyn_inst.hh index d29257a52..e94c44151 100644 --- a/cpu/base_dyn_inst.hh +++ b/cpu/base_dyn_inst.hh @@ -51,7 +51,6 @@ */ // Forward declaration. -template <class ISA> class StaticInstPtr; template <class Impl> @@ -61,25 +60,20 @@ class BaseDynInst : public FastAlloc, public RefCounted // Typedef for the CPU. typedef typename Impl::FullCPU FullCPU; - //Typedef to get the ISA. - typedef typename Impl::ISA ISA; - /// Binary machine instruction type. - typedef typename ISA::MachInst MachInst; - /// Memory address type. - typedef typename ISA::Addr Addr; + typedef TheISA::MachInst MachInst; /// Logical register index type. - typedef typename ISA::RegIndex RegIndex; + typedef TheISA::RegIndex RegIndex; /// Integer register index type. - typedef typename ISA::IntReg IntReg; + typedef TheISA::IntReg IntReg; enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; /** The static inst used by this dyn inst. */ - StaticInstPtr<ISA> staticInst; + StaticInstPtr staticInst; //////////////////////////////////////////// // @@ -214,7 +208,7 @@ class BaseDynInst : public FastAlloc, public RefCounted FullCPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ - BaseDynInst(StaticInstPtr<ISA> &_staticInst); + BaseDynInst(StaticInstPtr &_staticInst); /** BaseDynInst destructor. */ ~BaseDynInst(); @@ -472,7 +466,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags) req->paddr = req->vaddr; #endif - if (fault == No_Fault) { + if (fault == NoFault) { fault = cpu->read(req, data, lqIdx); } else { // Return a fixed value to keep simulation deterministic even @@ -520,14 +514,14 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) req->paddr = req->vaddr; #endif - if (fault == No_Fault) { + if (fault == NoFault) { fault = cpu->write(req, data, sqIdx); } if (res) { // always return some result to keep misspeculated paths // (which will ignore faults) deterministic - *res = (fault == No_Fault) ? req->result : 0; + *res = (fault == NoFault) ? req->result : 0; } return fault; diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 846be831a..3e0d77254 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -35,6 +35,7 @@ #include "sim/host.hh" #include "sim/serialize.hh" #include "arch/isa_traits.hh" +//#include "arch/isa_registers.hh" #include "sim/byteswap.hh" // forward declaration: see functional_memory.hh @@ -66,6 +67,10 @@ namespace Kernel { class Binning; class Statistics; } class ExecContext { + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; + typedef TheISA::MiscRegFile MiscRegFile; public: enum Status { @@ -80,7 +85,7 @@ class ExecContext Active, /// Temporarily inactive. Entered while waiting for - /// synchronization, etc. + /// initialization,synchronization, etc. Suspended, /// Permanently shut down. Entered when target executes @@ -95,6 +100,8 @@ class ExecContext public: Status status() const { return _status; } + void setStatus(Status newStatus) { _status = newStatus; } + /// Set the status to Active. Optional delay indicates number of /// cycles to wait before beginning execution. void activate(int delay = 1); @@ -240,7 +247,7 @@ class ExecContext // put the asid in the upper 16 bits of the paddr req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return No_Fault; + return NoFault; } Fault translateInstReq(MemReqPtr &req) { @@ -301,7 +308,7 @@ class ExecContext << "on cpu " << req->xc->cpu_id << std::endl; } - return No_Fault; + return NoFault; } else req->xc->storeCondFailures = 0; } @@ -431,15 +438,15 @@ class ExecContext void trap(Fault fault); #if !FULL_SYSTEM - IntReg getSyscallArg(int i) + TheISA::IntReg getSyscallArg(int i) { - return regs.intRegFile[ArgumentReg0 + i]; + return regs.intRegFile[TheISA::ArgumentReg0 + i]; } // used to shift args for indirect syscall - void setSyscallArg(int i, IntReg val) + void setSyscallArg(int i, TheISA::IntReg val) { - regs.intRegFile[ArgumentReg0 + i] = val; + regs.intRegFile[TheISA::ArgumentReg0 + i] = val; } void setSyscallReturn(SyscallReturn return_value) @@ -451,11 +458,11 @@ class ExecContext if (return_value.successful()) { // no error regs.intRegFile[RegA3] = 0; - regs.intRegFile[ReturnValueReg] = return_value.value(); + regs.intRegFile[TheISA::ReturnValueReg] = return_value.value(); } else { // got an error, return details - regs.intRegFile[RegA3] = (IntReg) -1; - regs.intRegFile[ReturnValueReg] = -return_value.value(); + regs.intRegFile[RegA3] = (TheISA::IntReg) -1; + regs.intRegFile[TheISA::ReturnValueReg] = -return_value.value(); } } diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh index 48d8966d8..67d042ec8 100644 --- a/cpu/exetrace.hh +++ b/cpu/exetrace.hh @@ -46,13 +46,14 @@ namespace Trace { class InstRecord : public Record { protected: + typedef TheISA::IntRegFile IntRegFile; // The following fields are initialized by the constructor and // thus guaranteed to be valid. BaseCPU *cpu; // need to make this ref-counted so it doesn't go away before we // dump the record - StaticInstPtr<TheISA> staticInst; + StaticInstPtr staticInst; Addr PC; bool misspeculating; unsigned thread; @@ -92,7 +93,7 @@ class InstRecord : public Record public: InstRecord(Tick _cycle, BaseCPU *_cpu, - const StaticInstPtr<TheISA> &_staticInst, + const StaticInstPtr &_staticInst, Addr _pc, bool spec, int _thread) : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc), misspeculating(spec), thread(_thread) @@ -169,7 +170,7 @@ InstRecord::setRegs(const IntRegFile ®s) inline InstRecord * getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu, - const StaticInstPtr<TheISA> staticInst, + const StaticInstPtr staticInst, Addr pc, int thread = 0) { if (DTRACE(InstExec) && diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc index 27f790fac..5a4024587 100644 --- a/cpu/memtest/memtest.cc +++ b/cpu/memtest/memtest.cc @@ -44,6 +44,7 @@ #include "sim/stats.hh" using namespace std; +using namespace TheISA; int TESTER_ALLOCATOR=0; diff --git a/cpu/o3/2bit_local_pred.hh b/cpu/o3/2bit_local_pred.hh index a97ce455c..97433e542 100644 --- a/cpu/o3/2bit_local_pred.hh +++ b/cpu/o3/2bit_local_pred.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_2BIT_LOCAL_PRED_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/o3/sat_counter.hh" class DefaultBP diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index 1e1a72af0..b35bcf9e3 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -39,8 +39,9 @@ template <class Impl> class AlphaFullCPU : public FullO3CPU<Impl> { + protected: + typedef TheISA::IntReg IntReg; public: - typedef typename Impl::ISA AlphaISA; typedef typename Impl::Params Params; public: @@ -87,7 +88,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> // put the asid in the upper 16 bits of the paddr req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return No_Fault; + return NoFault; } Fault translateInstReq(MemReqPtr &req) @@ -259,7 +260,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> << "on cpu " << this->cpu_id << std::endl; } - return No_Fault; + return NoFault; } else req->xc->storeCondFailures = 0; } diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh index 3b16975a9..7ec1ba663 100644 --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@ -280,9 +280,9 @@ AlphaFullCPU<Impl>::hwrei() uint64_t *ipr = getIpr(); if (!inPalMode()) - return Unimplemented_Opcode_Fault; + return UnimplementedOpcodeFault; - setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); + this->setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); // kernelStats.hwrei(); @@ -292,7 +292,7 @@ AlphaFullCPU<Impl>::hwrei() this->checkInterrupts = true; // FIXME: XXX check for interrupts? XXX - return No_Fault; + return NoFault; } template <class Impl> @@ -329,22 +329,22 @@ AlphaFullCPU<Impl>::trap(Fault fault) // miss uint64_t PC = this->commit.readCommitPC(); - DPRINTF(Fault, "Fault %s\n", FaultName(fault)); - this->recordEvent(csprintf("Fault %s", FaultName(fault))); + DPRINTF(Fault, "Fault %s\n", fault ? fault->name : "name"); + this->recordEvent(csprintf("Fault %s", fault ? fault->name : "name")); // kernelStats.fault(fault); - if (fault == Arithmetic_Fault) + if (fault == ArithmeticFault) panic("Arithmetic traps are unimplemented!"); - typename AlphaISA::InternalProcReg *ipr = getIpr(); + AlphaISA::InternalProcReg *ipr = getIpr(); // exception restart address - Get the commit PC - if (fault != Interrupt_Fault || !inPalMode(PC)) + if (fault != InterruptFault || !inPalMode(PC)) ipr[AlphaISA::IPR_EXC_ADDR] = PC; - if (fault == Pal_Fault || fault == Arithmetic_Fault /* || - fault == Interrupt_Fault && !PC_PAL(regs.pc) */) { + if (fault == PalFault || fault == ArithmeticFault /* || + fault == InterruptFault && !PC_PAL(regs.pc) */) { // traps... skip faulting instruction ipr[AlphaISA::IPR_EXC_ADDR] += 4; } @@ -353,7 +353,7 @@ AlphaFullCPU<Impl>::trap(Fault fault) swapPALShadow(true); this->regFile.setPC( ipr[AlphaISA::IPR_PAL_BASE] + - AlphaISA::fault_addr[fault] ); + AlphaISA::fault_addr(fault) ); this->regFile.setNextPC(PC + sizeof(MachInst)); } diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh index bb90bf21a..f282c287c 100644 --- a/cpu/o3/alpha_dyn_inst.hh +++ b/cpu/o3/alpha_dyn_inst.hh @@ -48,21 +48,16 @@ class AlphaDynInst : public BaseDynInst<Impl> /** Typedef for the CPU. */ typedef typename Impl::FullCPU FullCPU; - /** Typedef to get the ISA. */ - typedef typename Impl::ISA ISA; - /** Binary machine instruction type. */ - typedef typename ISA::MachInst MachInst; - /** Memory address type. */ - typedef typename ISA::Addr Addr; + typedef TheISA::MachInst MachInst; /** Logical register index type. */ - typedef typename ISA::RegIndex RegIndex; + typedef TheISA::RegIndex RegIndex; /** Integer register index type. */ - typedef typename ISA::IntReg IntReg; + typedef TheISA::IntReg IntReg; enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; public: @@ -71,7 +66,7 @@ class AlphaDynInst : public BaseDynInst<Impl> FullCPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ - AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst); + AlphaDynInst(StaticInstPtr &_staticInst); /** Executes the instruction.*/ Fault execute() @@ -130,22 +125,22 @@ class AlphaDynInst : public BaseDynInst<Impl> // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntReg(const StaticInst<ISA> *si, int idx) + uint64_t readIntReg(const StaticInst *si, int idx) { return this->cpu->readIntReg(_srcRegIdx[idx]); } - float readFloatRegSingle(const StaticInst<ISA> *si, int idx) + float readFloatRegSingle(const StaticInst *si, int idx) { return this->cpu->readFloatRegSingle(_srcRegIdx[idx]); } - double readFloatRegDouble(const StaticInst<ISA> *si, int idx) + double readFloatRegDouble(const StaticInst *si, int idx) { return this->cpu->readFloatRegDouble(_srcRegIdx[idx]); } - uint64_t readFloatRegInt(const StaticInst<ISA> *si, int idx) + uint64_t readFloatRegInt(const StaticInst *si, int idx) { return this->cpu->readFloatRegInt(_srcRegIdx[idx]); } @@ -153,25 +148,25 @@ class AlphaDynInst : public BaseDynInst<Impl> /** @todo: Make results into arrays so they can handle multiple dest * registers. */ - void setIntReg(const StaticInst<ISA> *si, int idx, uint64_t val) + void setIntReg(const StaticInst *si, int idx, uint64_t val) { this->cpu->setIntReg(_destRegIdx[idx], val); this->instResult.integer = val; } - void setFloatRegSingle(const StaticInst<ISA> *si, int idx, float val) + void setFloatRegSingle(const StaticInst *si, int idx, float val) { this->cpu->setFloatRegSingle(_destRegIdx[idx], val); this->instResult.fp = val; } - void setFloatRegDouble(const StaticInst<ISA> *si, int idx, double val) + void setFloatRegDouble(const StaticInst *si, int idx, double val) { this->cpu->setFloatRegDouble(_destRegIdx[idx], val); this->instResult.dbl = val; } - void setFloatRegInt(const StaticInst<ISA> *si, int idx, uint64_t val) + void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) { this->cpu->setFloatRegInt(_destRegIdx[idx], val); this->instResult.integer = val; diff --git a/cpu/o3/alpha_dyn_inst_impl.hh b/cpu/o3/alpha_dyn_inst_impl.hh index d1ebb812d..eebe7675a 100644 --- a/cpu/o3/alpha_dyn_inst_impl.hh +++ b/cpu/o3/alpha_dyn_inst_impl.hh @@ -50,7 +50,7 @@ AlphaDynInst<Impl>::AlphaDynInst(MachInst inst, Addr PC, Addr Pred_PC, } template <class Impl> -AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst) +AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst) : BaseDynInst<Impl>(_staticInst) { // Make sure to have the renamed register entries set to the same diff --git a/cpu/o3/alpha_impl.hh b/cpu/o3/alpha_impl.hh index 6c1156041..5e39fcb37 100644 --- a/cpu/o3/alpha_impl.hh +++ b/cpu/o3/alpha_impl.hh @@ -51,11 +51,8 @@ class AlphaFullCPU; */ struct AlphaSimpleImpl { - /** The ISA to be used. */ - typedef AlphaISA ISA; - /** The type of MachInst. */ - typedef ISA::MachInst MachInst; + typedef TheISA::MachInst MachInst; /** The CPU policy to be used (ie fetch, decode, etc.). */ typedef SimpleCPUPolicy<AlphaSimpleImpl> CPUPol; diff --git a/cpu/o3/bpred_unit_impl.hh b/cpu/o3/bpred_unit_impl.hh index 9cb2e0490..8d16a0cdf 100644 --- a/cpu/o3/bpred_unit_impl.hh +++ b/cpu/o3/bpred_unit_impl.hh @@ -98,6 +98,8 @@ TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC) // Save off record of branch stuff so the RAS can be fixed // up once it's done. + using TheISA::MachInst; + bool pred_taken = false; Addr target; diff --git a/cpu/o3/btb.cc b/cpu/o3/btb.cc index 7671e61e2..2d39c3856 100644 --- a/cpu/o3/btb.cc +++ b/cpu/o3/btb.cc @@ -30,6 +30,8 @@ #include "base/trace.hh" #include "cpu/o3/btb.hh" +using namespace TheISA; + DefaultBTB::DefaultBTB(unsigned _numEntries, unsigned _tagBits, unsigned _instShiftAmt) diff --git a/cpu/o3/btb.hh b/cpu/o3/btb.hh index a4ddfecb4..77bdc32ea 100644 --- a/cpu/o3/btb.hh +++ b/cpu/o3/btb.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_BTB_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" class DefaultBTB { diff --git a/cpu/o3/commit.hh b/cpu/o3/commit.hh index 6ddc8d6b9..580c1a316 100644 --- a/cpu/o3/commit.hh +++ b/cpu/o3/commit.hh @@ -52,7 +52,6 @@ class SimpleCommit { public: // Typedefs from the Impl. - typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; diff --git a/cpu/o3/commit_impl.hh b/cpu/o3/commit_impl.hh index dc0986772..e289bc0c0 100644 --- a/cpu/o3/commit_impl.hh +++ b/cpu/o3/commit_impl.hh @@ -395,7 +395,7 @@ SimpleCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Check if the instruction caused a fault. If so, trap. Fault inst_fault = head_inst->getFault(); - if (inst_fault != No_Fault && inst_fault != Fake_Mem_Fault) { + if (inst_fault != NoFault) { if (!head_inst->isNop()) { #if FULL_SYSTEM cpu->trap(inst_fault); diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc index 6ea0ed7c7..706657887 100644 --- a/cpu/o3/cpu.cc +++ b/cpu/o3/cpu.cc @@ -84,14 +84,14 @@ FullO3CPU<Impl>::FullO3CPU(Params ¶ms) regFile(params.numPhysIntRegs, params.numPhysFloatRegs), - freeList(Impl::ISA::NumIntRegs, params.numPhysIntRegs, - Impl::ISA::NumFloatRegs, params.numPhysFloatRegs), + freeList(TheISA::NumIntRegs, params.numPhysIntRegs, + TheISA::NumFloatRegs, params.numPhysFloatRegs), - renameMap(Impl::ISA::NumIntRegs, params.numPhysIntRegs, - Impl::ISA::NumFloatRegs, params.numPhysFloatRegs, - Impl::ISA::NumMiscRegs, - Impl::ISA::ZeroReg, - Impl::ISA::ZeroReg + Impl::ISA::NumIntRegs), + renameMap(TheISA::NumIntRegs, params.numPhysIntRegs, + TheISA::NumFloatRegs, params.numPhysFloatRegs, + TheISA::NumMiscRegs, + TheISA::ZeroReg, + TheISA::ZeroReg + TheISA::NumIntRegs), rob(params.numROBEntries, params.squashWidth), @@ -253,13 +253,13 @@ FullO3CPU<Impl>::init() ExecContext *src_xc = thread[0]; #endif // First loop through the integer registers. - for (int i = 0; i < Impl::ISA::NumIntRegs; ++i) + for (int i = 0; i < TheISA::NumIntRegs; ++i) { regFile.intRegFile[i] = src_xc->regs.intRegFile[i]; } // Then loop through the floating point registers. - for (int i = 0; i < Impl::ISA::NumFloatRegs; ++i) + for (int i = 0; i < TheISA::NumFloatRegs; ++i) { regFile.floatRegFile[i].d = src_xc->regs.floatRegFile.d[i]; regFile.floatRegFile[i].q = src_xc->regs.floatRegFile.q[i]; diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh index 75dca5056..321d61dce 100644 --- a/cpu/o3/cpu.hh +++ b/cpu/o3/cpu.hh @@ -78,7 +78,6 @@ class FullO3CPU : public BaseFullCPU { public: //Put typedefs from the Impl here. - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPolicy; typedef typename Impl::Params Params; typedef typename Impl::DynInstPtr DynInstPtr; @@ -153,11 +152,11 @@ class FullO3CPU : public BaseFullCPU /** Get instruction asid. */ int getInstAsid() - { return ITB_ASN_ASN(regFile.getIpr()[ISA::IPR_ITB_ASN]); } + { return ITB_ASN_ASN(regFile.getIpr()[TheISA::IPR_ITB_ASN]); } /** Get data asid. */ int getDataAsid() - { return DTB_ASN_ASN(regFile.getIpr()[ISA::IPR_DTB_ASN]); } + { return DTB_ASN_ASN(regFile.getIpr()[TheISA::IPR_DTB_ASN]); } #else bool validInstAddr(Addr addr) { return thread[0]->validInstAddr(addr); } diff --git a/cpu/o3/decode.hh b/cpu/o3/decode.hh index 42313d83a..5b9a0f822 100644 --- a/cpu/o3/decode.hh +++ b/cpu/o3/decode.hh @@ -39,7 +39,6 @@ class SimpleDecode { private: // Typedefs from the Impl. - typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; @@ -50,9 +49,6 @@ class SimpleDecode typedef typename CPUPol::DecodeStruct DecodeStruct; typedef typename CPUPol::TimeStruct TimeStruct; - // Typedefs from the ISA. - typedef typename ISA::Addr Addr; - public: // The only time decode will become blocked is if dispatch becomes // blocked, which means IQ or ROB is probably full. diff --git a/cpu/o3/fetch.hh b/cpu/o3/fetch.hh index 24e445f0b..cc64800d9 100644 --- a/cpu/o3/fetch.hh +++ b/cpu/o3/fetch.hh @@ -49,7 +49,6 @@ class SimpleFetch { public: /** Typedefs from Impl. */ - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; @@ -61,7 +60,7 @@ class SimpleFetch typedef typename CPUPol::TimeStruct TimeStruct; /** Typedefs from ISA. */ - typedef typename ISA::MachInst MachInst; + typedef TheISA::MachInst MachInst; public: enum Status { @@ -141,7 +140,7 @@ class SimpleFetch // We fold in the PISA 64- to 32-bit conversion here as well. Addr icacheBlockAlignPC(Addr addr) { - addr = ISA::realPCToFetchPC(addr); + addr = TheISA::realPCToFetchPC(addr); return (addr & ~(cacheBlkMask)); } diff --git a/cpu/o3/fetch_impl.hh b/cpu/o3/fetch_impl.hh index cd1ed1351..8029fc732 100644 --- a/cpu/o3/fetch_impl.hh +++ b/cpu/o3/fetch_impl.hh @@ -236,7 +236,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC) unsigned flags = 0; #endif // FULL_SYSTEM - Fault fault = No_Fault; + Fault fault = NoFault; // Align the fetch PC so it's at the start of a cache block. fetch_PC = icacheBlockAlignPC(fetch_PC); @@ -258,7 +258,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC) // If translation was successful, attempt to read the first // instruction. - if (fault == No_Fault) { + if (fault == NoFault) { DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); fault = cpu->mem->read(memReq, cacheData); // This read may change when the mem interface changes. @@ -268,7 +268,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC) // Now do the timing access to see whether or not the instruction // exists within the cache. - if (icacheInterface && fault == No_Fault) { + if (icacheInterface && fault == NoFault) { DPRINTF(Fetch, "Fetch: Doing timing memory access.\n"); memReq->completionEvent = NULL; @@ -468,7 +468,7 @@ SimpleFetch<Impl>::fetch() Addr fetch_PC = cpu->readPC(); // Fault code for memory access. - Fault fault = No_Fault; + Fault fault = NoFault; // If returning from the delay of a cache miss, then update the status // to running, otherwise do the cache access. Possibly move this up @@ -506,7 +506,7 @@ SimpleFetch<Impl>::fetch() unsigned offset = fetch_PC & cacheBlkMask; unsigned fetched; - if (fault == No_Fault) { + if (fault == NoFault) { // If the read of the first instruction was successful, then grab the // instructions from the rest of the cache line and put them into the // queue heading to decode. @@ -582,7 +582,7 @@ SimpleFetch<Impl>::fetch() // Or might want to leave setting the PC to the main CPU, with fetch // only changing the nextPC (will require correct determination of // next PC). - if (fault == No_Fault) { + if (fault == NoFault) { DPRINTF(Fetch, "Fetch: Setting PC to %08p.\n", next_PC); cpu->setPC(next_PC); cpu->setNextPC(next_PC + instSize); diff --git a/cpu/o3/free_list.hh b/cpu/o3/free_list.hh index 733d142fc..0b85dba1e 100644 --- a/cpu/o3/free_list.hh +++ b/cpu/o3/free_list.hh @@ -32,7 +32,7 @@ #include <iostream> #include <queue> -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "base/trace.hh" #include "base/traceflags.hh" #include "cpu/o3/comm.hh" diff --git a/cpu/o3/iew.hh b/cpu/o3/iew.hh index af23c6f45..1e370d4e6 100644 --- a/cpu/o3/iew.hh +++ b/cpu/o3/iew.hh @@ -45,7 +45,6 @@ class SimpleIEW { private: //Typedefs from Impl - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::FullCPU FullCPU; diff --git a/cpu/o3/iew_impl.hh b/cpu/o3/iew_impl.hh index b8a2b4dc9..85217dd10 100644 --- a/cpu/o3/iew_impl.hh +++ b/cpu/o3/iew_impl.hh @@ -256,7 +256,7 @@ SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) toCommit->branchMispredict = true; // Prediction was incorrect, so send back inverse. toCommit->branchTaken = inst->readNextPC() != - (inst->readPC() + sizeof(MachInst)); + (inst->readPC() + sizeof(TheISA::MachInst)); } template<class Impl> diff --git a/cpu/o3/ras.hh b/cpu/o3/ras.hh index bbc4162a6..46d98181e 100644 --- a/cpu/o3/ras.hh +++ b/cpu/o3/ras.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_RAS_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" class ReturnAddrStack { diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh index 4d47b8f9c..ee7b8858e 100644 --- a/cpu/o3/regfile.hh +++ b/cpu/o3/regfile.hh @@ -32,6 +32,7 @@ // @todo: Destructor #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/faults.hh" #include "base/trace.hh" #include "config/full_system.hh" #include "cpu/o3/comm.hh" @@ -51,6 +52,10 @@ using namespace EV5; template <class Impl> class PhysRegFile { + protected: + typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::MiscRegFile MiscRegFile; //Note that most of the definitions of the IntReg, FloatReg, etc. exist //within the Impl/ISA class and not within this PhysRegFile class. @@ -61,7 +66,6 @@ class PhysRegFile //Will make these registers public for now, but they probably should //be private eventually with some accessor functions. public: - typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; PhysRegFile(unsigned _numPhysicalIntRegs, @@ -280,73 +284,73 @@ PhysRegFile<Impl>::readIpr(int idx, Fault &fault) uint64_t retval = 0; // return value, default 0 switch (idx) { - case ISA::IPR_PALtemp0: - case ISA::IPR_PALtemp1: - case ISA::IPR_PALtemp2: - case ISA::IPR_PALtemp3: - case ISA::IPR_PALtemp4: - case ISA::IPR_PALtemp5: - case ISA::IPR_PALtemp6: - case ISA::IPR_PALtemp7: - case ISA::IPR_PALtemp8: - case ISA::IPR_PALtemp9: - case ISA::IPR_PALtemp10: - case ISA::IPR_PALtemp11: - case ISA::IPR_PALtemp12: - case ISA::IPR_PALtemp13: - case ISA::IPR_PALtemp14: - case ISA::IPR_PALtemp15: - case ISA::IPR_PALtemp16: - case ISA::IPR_PALtemp17: - case ISA::IPR_PALtemp18: - case ISA::IPR_PALtemp19: - case ISA::IPR_PALtemp20: - case ISA::IPR_PALtemp21: - case ISA::IPR_PALtemp22: - case ISA::IPR_PALtemp23: - case ISA::IPR_PAL_BASE: - - case ISA::IPR_IVPTBR: - case ISA::IPR_DC_MODE: - case ISA::IPR_MAF_MODE: - case ISA::IPR_ISR: - case ISA::IPR_EXC_ADDR: - case ISA::IPR_IC_PERR_STAT: - case ISA::IPR_DC_PERR_STAT: - case ISA::IPR_MCSR: - case ISA::IPR_ASTRR: - case ISA::IPR_ASTER: - case ISA::IPR_SIRR: - case ISA::IPR_ICSR: - case ISA::IPR_ICM: - case ISA::IPR_DTB_CM: - case ISA::IPR_IPLR: - case ISA::IPR_INTID: - case ISA::IPR_PMCTR: + case TheISA::IPR_PALtemp0: + case TheISA::IPR_PALtemp1: + case TheISA::IPR_PALtemp2: + case TheISA::IPR_PALtemp3: + case TheISA::IPR_PALtemp4: + case TheISA::IPR_PALtemp5: + case TheISA::IPR_PALtemp6: + case TheISA::IPR_PALtemp7: + case TheISA::IPR_PALtemp8: + case TheISA::IPR_PALtemp9: + case TheISA::IPR_PALtemp10: + case TheISA::IPR_PALtemp11: + case TheISA::IPR_PALtemp12: + case TheISA::IPR_PALtemp13: + case TheISA::IPR_PALtemp14: + case TheISA::IPR_PALtemp15: + case TheISA::IPR_PALtemp16: + case TheISA::IPR_PALtemp17: + case TheISA::IPR_PALtemp18: + case TheISA::IPR_PALtemp19: + case TheISA::IPR_PALtemp20: + case TheISA::IPR_PALtemp21: + case TheISA::IPR_PALtemp22: + case TheISA::IPR_PALtemp23: + case TheISA::IPR_PAL_BASE: + + case TheISA::IPR_IVPTBR: + case TheISA::IPR_DC_MODE: + case TheISA::IPR_MAF_MODE: + case TheISA::IPR_ISR: + case TheISA::IPR_EXC_ADDR: + case TheISA::IPR_IC_PERR_STAT: + case TheISA::IPR_DC_PERR_STAT: + case TheISA::IPR_MCSR: + case TheISA::IPR_ASTRR: + case TheISA::IPR_ASTER: + case TheISA::IPR_SIRR: + case TheISA::IPR_ICSR: + case TheISA::IPR_ICM: + case TheISA::IPR_DTB_CM: + case TheISA::IPR_IPLR: + case TheISA::IPR_INTID: + case TheISA::IPR_PMCTR: // no side-effect retval = ipr[idx]; break; - case ISA::IPR_CC: + case TheISA::IPR_CC: retval |= ipr[idx] & ULL(0xffffffff00000000); retval |= curTick & ULL(0x00000000ffffffff); break; - case ISA::IPR_VA: + case TheISA::IPR_VA: retval = ipr[idx]; break; - case ISA::IPR_VA_FORM: - case ISA::IPR_MM_STAT: - case ISA::IPR_IFAULT_VA_FORM: - case ISA::IPR_EXC_MASK: - case ISA::IPR_EXC_SUM: + case TheISA::IPR_VA_FORM: + case TheISA::IPR_MM_STAT: + case TheISA::IPR_IFAULT_VA_FORM: + case TheISA::IPR_EXC_MASK: + case TheISA::IPR_EXC_SUM: retval = ipr[idx]; break; - case ISA::IPR_DTB_PTE: + case TheISA::IPR_DTB_PTE: { - typename ISA::PTE &pte = cpu->dtb->index(1); + TheISA::PTE &pte = cpu->dtb->index(1); retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32; retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8; @@ -359,21 +363,21 @@ PhysRegFile<Impl>::readIpr(int idx, Fault &fault) break; // write only registers - case ISA::IPR_HWINT_CLR: - case ISA::IPR_SL_XMIT: - case ISA::IPR_DC_FLUSH: - case ISA::IPR_IC_FLUSH: - case ISA::IPR_ALT_MODE: - case ISA::IPR_DTB_IA: - case ISA::IPR_DTB_IAP: - case ISA::IPR_ITB_IA: - case ISA::IPR_ITB_IAP: - fault = Unimplemented_Opcode_Fault; + case TheISA::IPR_HWINT_CLR: + case TheISA::IPR_SL_XMIT: + case TheISA::IPR_DC_FLUSH: + case TheISA::IPR_IC_FLUSH: + case TheISA::IPR_ALT_MODE: + case TheISA::IPR_DTB_IA: + case TheISA::IPR_DTB_IAP: + case TheISA::IPR_ITB_IA: + case TheISA::IPR_ITB_IAP: + fault = UnimplementedOpcodeFault; break; default: // invalid IPR - fault = Unimplemented_Opcode_Fault; + fault = UnimplementedOpcodeFault; break; } @@ -389,195 +393,195 @@ PhysRegFile<Impl>::setIpr(int idx, uint64_t val) uint64_t old; switch (idx) { - case ISA::IPR_PALtemp0: - case ISA::IPR_PALtemp1: - case ISA::IPR_PALtemp2: - case ISA::IPR_PALtemp3: - case ISA::IPR_PALtemp4: - case ISA::IPR_PALtemp5: - case ISA::IPR_PALtemp6: - case ISA::IPR_PALtemp7: - case ISA::IPR_PALtemp8: - case ISA::IPR_PALtemp9: - case ISA::IPR_PALtemp10: - case ISA::IPR_PALtemp11: - case ISA::IPR_PALtemp12: - case ISA::IPR_PALtemp13: - case ISA::IPR_PALtemp14: - case ISA::IPR_PALtemp15: - case ISA::IPR_PALtemp16: - case ISA::IPR_PALtemp17: - case ISA::IPR_PALtemp18: - case ISA::IPR_PALtemp19: - case ISA::IPR_PALtemp20: - case ISA::IPR_PALtemp21: - case ISA::IPR_PALtemp22: - case ISA::IPR_PAL_BASE: - case ISA::IPR_IC_PERR_STAT: - case ISA::IPR_DC_PERR_STAT: - case ISA::IPR_PMCTR: + case TheISA::IPR_PALtemp0: + case TheISA::IPR_PALtemp1: + case TheISA::IPR_PALtemp2: + case TheISA::IPR_PALtemp3: + case TheISA::IPR_PALtemp4: + case TheISA::IPR_PALtemp5: + case TheISA::IPR_PALtemp6: + case TheISA::IPR_PALtemp7: + case TheISA::IPR_PALtemp8: + case TheISA::IPR_PALtemp9: + case TheISA::IPR_PALtemp10: + case TheISA::IPR_PALtemp11: + case TheISA::IPR_PALtemp12: + case TheISA::IPR_PALtemp13: + case TheISA::IPR_PALtemp14: + case TheISA::IPR_PALtemp15: + case TheISA::IPR_PALtemp16: + case TheISA::IPR_PALtemp17: + case TheISA::IPR_PALtemp18: + case TheISA::IPR_PALtemp19: + case TheISA::IPR_PALtemp20: + case TheISA::IPR_PALtemp21: + case TheISA::IPR_PALtemp22: + case TheISA::IPR_PAL_BASE: + case TheISA::IPR_IC_PERR_STAT: + case TheISA::IPR_DC_PERR_STAT: + case TheISA::IPR_PMCTR: // write entire quad w/ no side-effect ipr[idx] = val; break; - case ISA::IPR_CC_CTL: + case TheISA::IPR_CC_CTL: // This IPR resets the cycle counter. We assume this only // happens once... let's verify that. assert(ipr[idx] == 0); ipr[idx] = 1; break; - case ISA::IPR_CC: + case TheISA::IPR_CC: // This IPR only writes the upper 64 bits. It's ok to write // all 64 here since we mask out the lower 32 in rpcc (see // isa_desc). ipr[idx] = val; break; - case ISA::IPR_PALtemp23: + case TheISA::IPR_PALtemp23: // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; break; - case ISA::IPR_DTB_PTE: + case TheISA::IPR_DTB_PTE: // write entire quad w/ no side-effect, tag is forthcoming ipr[idx] = val; break; - case ISA::IPR_EXC_ADDR: + case TheISA::IPR_EXC_ADDR: // second least significant bit in PC is always zero ipr[idx] = val & ~2; break; - case ISA::IPR_ASTRR: - case ISA::IPR_ASTER: + case TheISA::IPR_ASTRR: + case TheISA::IPR_ASTER: // only write least significant four bits - privilege mask ipr[idx] = val & 0xf; break; - case ISA::IPR_IPLR: + case TheISA::IPR_IPLR: // only write least significant five bits - interrupt level ipr[idx] = val & 0x1f; break; - case ISA::IPR_DTB_CM: + case TheISA::IPR_DTB_CM: - case ISA::IPR_ICM: + case TheISA::IPR_ICM: // only write two mode bits - processor mode ipr[idx] = val & 0x18; break; - case ISA::IPR_ALT_MODE: + case TheISA::IPR_ALT_MODE: // only write two mode bits - processor mode ipr[idx] = val & 0x18; break; - case ISA::IPR_MCSR: + case TheISA::IPR_MCSR: // more here after optimization... ipr[idx] = val; break; - case ISA::IPR_SIRR: + case TheISA::IPR_SIRR: // only write software interrupt mask ipr[idx] = val & 0x7fff0; break; - case ISA::IPR_ICSR: + case TheISA::IPR_ICSR: ipr[idx] = val & ULL(0xffffff0300); break; - case ISA::IPR_IVPTBR: - case ISA::IPR_MVPTBR: + case TheISA::IPR_IVPTBR: + case TheISA::IPR_MVPTBR: ipr[idx] = val & ULL(0xffffffffc0000000); break; - case ISA::IPR_DC_TEST_CTL: + case TheISA::IPR_DC_TEST_CTL: ipr[idx] = val & 0x1ffb; break; - case ISA::IPR_DC_MODE: - case ISA::IPR_MAF_MODE: + case TheISA::IPR_DC_MODE: + case TheISA::IPR_MAF_MODE: ipr[idx] = val & 0x3f; break; - case ISA::IPR_ITB_ASN: + case TheISA::IPR_ITB_ASN: ipr[idx] = val & 0x7f0; break; - case ISA::IPR_DTB_ASN: + case TheISA::IPR_DTB_ASN: ipr[idx] = val & ULL(0xfe00000000000000); break; - case ISA::IPR_EXC_SUM: - case ISA::IPR_EXC_MASK: + case TheISA::IPR_EXC_SUM: + case TheISA::IPR_EXC_MASK: // any write to this register clears it ipr[idx] = 0; break; - case ISA::IPR_INTID: - case ISA::IPR_SL_RCV: - case ISA::IPR_MM_STAT: - case ISA::IPR_ITB_PTE_TEMP: - case ISA::IPR_DTB_PTE_TEMP: + case TheISA::IPR_INTID: + case TheISA::IPR_SL_RCV: + case TheISA::IPR_MM_STAT: + case TheISA::IPR_ITB_PTE_TEMP: + case TheISA::IPR_DTB_PTE_TEMP: // read-only registers - return Unimplemented_Opcode_Fault; + return UnimplementedOpcodeFault; - case ISA::IPR_HWINT_CLR: - case ISA::IPR_SL_XMIT: - case ISA::IPR_DC_FLUSH: - case ISA::IPR_IC_FLUSH: + case TheISA::IPR_HWINT_CLR: + case TheISA::IPR_SL_XMIT: + case TheISA::IPR_DC_FLUSH: + case TheISA::IPR_IC_FLUSH: // the following are write only ipr[idx] = val; break; - case ISA::IPR_DTB_IA: + case TheISA::IPR_DTB_IA: // really a control write ipr[idx] = 0; cpu->dtb->flushAll(); break; - case ISA::IPR_DTB_IAP: + case TheISA::IPR_DTB_IAP: // really a control write ipr[idx] = 0; cpu->dtb->flushProcesses(); break; - case ISA::IPR_DTB_IS: + case TheISA::IPR_DTB_IS: // really a control write ipr[idx] = val; - cpu->dtb->flushAddr(val, DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN])); + cpu->dtb->flushAddr(val, DTB_ASN_ASN(ipr[TheISA::IPR_DTB_ASN])); break; - case ISA::IPR_DTB_TAG: { - struct ISA::PTE pte; + case TheISA::IPR_DTB_TAG: { + struct TheISA::PTE pte; // FIXME: granularity hints NYI... - if (DTB_PTE_GH(ipr[ISA::IPR_DTB_PTE]) != 0) + if (DTB_PTE_GH(ipr[TheISA::IPR_DTB_PTE]) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - pte.ppn = DTB_PTE_PPN(ipr[ISA::IPR_DTB_PTE]); - pte.xre = DTB_PTE_XRE(ipr[ISA::IPR_DTB_PTE]); - pte.xwe = DTB_PTE_XWE(ipr[ISA::IPR_DTB_PTE]); - pte.fonr = DTB_PTE_FONR(ipr[ISA::IPR_DTB_PTE]); - pte.fonw = DTB_PTE_FONW(ipr[ISA::IPR_DTB_PTE]); - pte.asma = DTB_PTE_ASMA(ipr[ISA::IPR_DTB_PTE]); - pte.asn = DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN]); + pte.ppn = DTB_PTE_PPN(ipr[TheISA::IPR_DTB_PTE]); + pte.xre = DTB_PTE_XRE(ipr[TheISA::IPR_DTB_PTE]); + pte.xwe = DTB_PTE_XWE(ipr[TheISA::IPR_DTB_PTE]); + pte.fonr = DTB_PTE_FONR(ipr[TheISA::IPR_DTB_PTE]); + pte.fonw = DTB_PTE_FONW(ipr[TheISA::IPR_DTB_PTE]); + pte.asma = DTB_PTE_ASMA(ipr[TheISA::IPR_DTB_PTE]); + pte.asn = DTB_ASN_ASN(ipr[TheISA::IPR_DTB_ASN]); // insert new TAG/PTE value into data TLB cpu->dtb->insert(val, pte); } break; - case ISA::IPR_ITB_PTE: { - struct ISA::PTE pte; + case TheISA::IPR_ITB_PTE: { + struct TheISA::PTE pte; // FIXME: granularity hints NYI... if (ITB_PTE_GH(val) != 0) @@ -593,41 +597,41 @@ PhysRegFile<Impl>::setIpr(int idx, uint64_t val) pte.fonr = ITB_PTE_FONR(val); pte.fonw = ITB_PTE_FONW(val); pte.asma = ITB_PTE_ASMA(val); - pte.asn = ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN]); + pte.asn = ITB_ASN_ASN(ipr[TheISA::IPR_ITB_ASN]); // insert new TAG/PTE value into data TLB - cpu->itb->insert(ipr[ISA::IPR_ITB_TAG], pte); + cpu->itb->insert(ipr[TheISA::IPR_ITB_TAG], pte); } break; - case ISA::IPR_ITB_IA: + case TheISA::IPR_ITB_IA: // really a control write ipr[idx] = 0; cpu->itb->flushAll(); break; - case ISA::IPR_ITB_IAP: + case TheISA::IPR_ITB_IAP: // really a control write ipr[idx] = 0; cpu->itb->flushProcesses(); break; - case ISA::IPR_ITB_IS: + case TheISA::IPR_ITB_IS: // really a control write ipr[idx] = val; - cpu->itb->flushAddr(val, ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN])); + cpu->itb->flushAddr(val, ITB_ASN_ASN(ipr[TheISA::IPR_ITB_ASN])); break; default: // invalid IPR - return Unimplemented_Opcode_Fault; + return UnimplementedOpcodeFault; } // no error... - return No_Fault; + return NoFault; } #endif // #if FULL_SYSTEM diff --git a/cpu/o3/rename.hh b/cpu/o3/rename.hh index a17ec7311..07b442964 100644 --- a/cpu/o3/rename.hh +++ b/cpu/o3/rename.hh @@ -46,7 +46,6 @@ class SimpleRename { public: // Typedefs from the Impl. - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::FullCPU FullCPU; @@ -62,7 +61,7 @@ class SimpleRename typedef typename CPUPol::RenameMap RenameMap; // Typedefs from the ISA. - typedef typename ISA::Addr Addr; + typedef TheISA::RegIndex RegIndex; public: // Rename will block if ROB becomes full or issue queue becomes full, diff --git a/cpu/o3/rename_map.hh b/cpu/o3/rename_map.hh index c44c7a1ea..57be4a64a 100644 --- a/cpu/o3/rename_map.hh +++ b/cpu/o3/rename_map.hh @@ -38,9 +38,13 @@ #include <vector> #include "cpu/o3/free_list.hh" +//For RegIndex +#include "arch/isa_traits.hh" class SimpleRenameMap { + protected: + typedef TheISA::RegIndex RegIndex; public: /** * Pair of a logical register and a physical register. Tells the diff --git a/cpu/o3/rob.hh b/cpu/o3/rob.hh index 29ec48007..1185564ad 100644 --- a/cpu/o3/rob.hh +++ b/cpu/o3/rob.hh @@ -47,6 +47,8 @@ template <class Impl> class ROB { + protected: + typedef TheISA::RegIndex RegIndex; public: //Typedefs from the Impl. typedef typename Impl::FullCPU FullCPU; diff --git a/cpu/o3/store_set.hh b/cpu/o3/store_set.hh index bcd590384..5a885d838 100644 --- a/cpu/o3/store_set.hh +++ b/cpu/o3/store_set.hh @@ -31,7 +31,7 @@ #include <vector> -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" class StoreSet diff --git a/cpu/o3/tournament_pred.hh b/cpu/o3/tournament_pred.hh index 58ea1a7d9..cb93c2f67 100644 --- a/cpu/o3/tournament_pred.hh +++ b/cpu/o3/tournament_pred.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_TOURNAMENT_PRED_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/o3/sat_counter.hh" class TournamentBP diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh index 5af77862a..667e2b3f8 100644 --- a/cpu/ozone/cpu.hh +++ b/cpu/ozone/cpu.hh @@ -77,7 +77,6 @@ class OoOCPU : public BaseCPU private: typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::ISA ISA; public: // main simulation loop (one cycle) @@ -320,7 +319,7 @@ class OoOCPU : public BaseCPU // put the asid in the upper 16 bits of the paddr req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return No_Fault; + return NoFault; } Fault translateInstReq(MemReqPtr &req) { @@ -378,12 +377,12 @@ class OoOCPU : public BaseCPU private: InstSeqNum globalSeqNum; - DynInstPtr renameTable[ISA::TotalNumRegs]; - DynInstPtr commitTable[ISA::TotalNumRegs]; + DynInstPtr renameTable[TheISA::TotalNumRegs]; + DynInstPtr commitTable[TheISA::TotalNumRegs]; // Might need a table of the shadow registers as well. #if FULL_SYSTEM - DynInstPtr palShadowTable[ISA::NumIntRegs]; + DynInstPtr palShadowTable[TheISA::NumIntRegs]; #endif public: @@ -402,47 +401,47 @@ class OoOCPU : public BaseCPU // rename table of DynInsts. Also these likely shouldn't be called very // often, other than when adding things into the xc during say a syscall. - uint64_t readIntReg(StaticInst<TheISA> *si, int idx) + uint64_t readIntReg(StaticInst *si, int idx) { return xc->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(StaticInst<TheISA> *si, int idx) + float readFloatRegSingle(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegSingle(reg_idx); } - double readFloatRegDouble(StaticInst<TheISA> *si, int idx) + double readFloatRegDouble(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegDouble(reg_idx); } - uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx) + uint64_t readFloatRegInt(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegInt(reg_idx); } - void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val) + void setIntReg(StaticInst *si, int idx, uint64_t val) { xc->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val) + void setFloatRegSingle(StaticInst *si, int idx, float val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegSingle(reg_idx, val); } - void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val) + void setFloatRegDouble(StaticInst *si, int idx, double val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegDouble(reg_idx, val); } - void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val) + void setFloatRegInt(StaticInst *si, int idx, uint64_t val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegInt(reg_idx, val); @@ -479,7 +478,7 @@ class OoOCPU : public BaseCPU // We fold in the PISA 64- to 32-bit conversion here as well. Addr icacheBlockAlignPC(Addr addr) { - addr = ISA::realPCToFetchPC(addr); + addr = TheISA::realPCToFetchPC(addr); return (addr & ~(cacheBlkMask)); } @@ -545,18 +544,18 @@ OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst) Fault fault = translateDataReadReq(readReq); // do functional access - if (fault == No_Fault) + if (fault == NoFault) fault = xc->mem->read(readReq, data); #if 0 if (traceData) { traceData->setAddr(addr); - if (fault == No_Fault) + if (fault == NoFault) traceData->setData(data); } #endif // if we have a cache, do cache access too - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { readReq->cmd = Read; readReq->completionEvent = NULL; readReq->time = curTick; @@ -598,10 +597,10 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags, Fault fault = translateDataWriteReq(writeReq); // do functional access - if (fault == No_Fault) + if (fault == NoFault) fault = xc->write(writeReq, data); - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { writeReq->cmd = Write; memcpy(writeReq->data,(uint8_t *)&data,writeReq->size); writeReq->completionEvent = NULL; @@ -614,7 +613,7 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags, } } - if (res && (fault == No_Fault)) + if (res && (fault == NoFault)) *res = writeReq->result; if (!dcacheInterface && (writeReq->flags & UNCACHEABLE)) diff --git a/cpu/profile.hh b/cpu/profile.hh index 58cd7e79f..18061f9bf 100644 --- a/cpu/profile.hh +++ b/cpu/profile.hh @@ -68,7 +68,7 @@ class FunctionProfile FunctionProfile(const SymbolTable *symtab); ~FunctionProfile(); - ProfileNode *consume(ExecContext *xc, StaticInstPtr<TheISA> inst); + ProfileNode *consume(ExecContext *xc, StaticInstPtr inst); ProfileNode *consume(const std::vector<Addr> &stack); void clear(); void dump(ExecContext *xc, std::ostream &out) const; @@ -76,7 +76,7 @@ class FunctionProfile }; inline ProfileNode * -FunctionProfile::consume(ExecContext *xc, StaticInstPtr<TheISA> inst) +FunctionProfile::consume(ExecContext *xc, StaticInstPtr inst) { if (!trace.trace(xc, inst)) return NULL; diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 2438e49f6..944bdbb0a 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -76,7 +76,7 @@ using namespace std; //The SimpleCPU does alpha only -using namespace LittleEndianGuest; +using namespace AlphaISA; SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) @@ -336,7 +336,7 @@ SimpleCPU::copySrcTranslate(Addr src) // Make sure block doesn't span page if (no_warn && - (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) && + (src & PageMask) != ((src + blk_size) & PageMask) && (src >> 40) != 0xfffffc) { warn("Copied block source spans pages %x.", src); no_warn = false; @@ -347,9 +347,9 @@ SimpleCPU::copySrcTranslate(Addr src) // translate to physical address Fault fault = xc->translateDataReadReq(memReq); - assert(fault != Alignment_Fault); + assert(fault != AlignmentFault); - if (fault == No_Fault) { + if (fault == NoFault) { xc->copySrcAddr = src; xc->copySrcPhysAddr = memReq->paddr + offset; } else { @@ -372,7 +372,7 @@ SimpleCPU::copy(Addr dest) // Make sure block doesn't span page if (no_warn && - (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) && + (dest & PageMask) != ((dest + blk_size) & PageMask) && (dest >> 40) != 0xfffffc) { no_warn = false; warn("Copied block destination spans pages %x. ", dest); @@ -382,9 +382,9 @@ SimpleCPU::copy(Addr dest) // translate to physical address Fault fault = xc->translateDataWriteReq(memReq); - assert(fault != Alignment_Fault); + assert(fault != AlignmentFault); - if (fault == No_Fault) { + if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; // Need to read straight from memory since we have more than 8 bytes. memReq->paddr = xc->copySrcPhysAddr; @@ -425,7 +425,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) Fault fault = xc->translateDataReadReq(memReq); // if we have a cache, do cache access too - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; @@ -445,7 +445,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) fault = xc->read(memReq, data); } - } else if(fault == No_Fault) { + } else if(fault == NoFault) { // do functional access fault = xc->read(memReq, data); @@ -510,10 +510,10 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) Fault fault = xc->translateDataWriteReq(memReq); // do functional access - if (fault == No_Fault) + if (fault == NoFault) fault = xc->write(memReq, data); - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; memcpy(memReq->data,(uint8_t *)&data,memReq->size); memReq->completionEvent = NULL; @@ -532,7 +532,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } } - if (res && (fault == No_Fault)) + if (res && (fault == NoFault)) *res = memReq->result; if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) @@ -651,7 +651,7 @@ SimpleCPU::tick() traceData = NULL; - Fault fault = No_Fault; + Fault fault = NoFault; #if FULL_SYSTEM if (checkInterrupts && check_interrupts() && !xc->inPalMode() && @@ -661,20 +661,20 @@ SimpleCPU::tick() checkInterrupts = false; IntReg *ipr = xc->regs.ipr; - if (xc->regs.ipr[TheISA::IPR_SIRR]) { - for (int i = TheISA::INTLEVEL_SOFTWARE_MIN; - i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) { - if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) { + if (xc->regs.ipr[IPR_SIRR]) { + for (int i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (ipr[IPR_SIRR] & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference - ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1; + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); } } } uint64_t interrupts = xc->cpu->intr_status(); - for (int i = TheISA::INTLEVEL_EXTERNAL_MIN; - i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) { + for (int i = INTLEVEL_EXTERNAL_MIN; + i < INTLEVEL_EXTERNAL_MAX; i++) { if (interrupts & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = i; @@ -682,16 +682,16 @@ SimpleCPU::tick() } } - if (ipr[TheISA::IPR_ASTRR]) + if (ipr[IPR_ASTRR]) panic("asynchronous traps not implemented\n"); - if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) { - ipr[TheISA::IPR_ISR] = summary; - ipr[TheISA::IPR_INTID] = ipl; - xc->ev5_trap(Interrupt_Fault); + if (ipl && ipl > xc->regs.ipr[IPR_IPLR]) { + ipr[IPR_ISR] = summary; + ipr[IPR_INTID] = ipl; + xc->ev5_trap(InterruptFault); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - ipr[TheISA::IPR_IPLR], ipl, summary); + ipr[IPR_IPLR], ipl, summary); } } #endif @@ -726,10 +726,10 @@ SimpleCPU::tick() fault = xc->translateInstReq(memReq); - if (fault == No_Fault) + if (fault == NoFault) fault = xc->mem->read(memReq, inst); - if (icacheInterface && fault == No_Fault) { + if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; memReq->time = curTick; @@ -751,7 +751,7 @@ SimpleCPU::tick() // If we've got a valid instruction (i.e., no fault on instruction // fetch), then execute it. - if (fault == No_Fault) { + if (fault == NoFault) { // keep an instruction count numInst++; @@ -762,7 +762,7 @@ SimpleCPU::tick() // decode the instruction inst = gtoh(inst); - curStaticInst = StaticInst<TheISA>::decode(inst); + curStaticInst = StaticInst::decode(inst); traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst, xc->regs.pc); @@ -808,9 +808,9 @@ SimpleCPU::tick() traceFunctions(xc->regs.pc); - } // if (fault == No_Fault) + } // if (fault == NoFault) - if (fault != No_Fault) { + if (fault != NoFault) { #if FULL_SYSTEM xc->ev5_trap(fault); #else // !FULL_SYSTEM diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh index 564749592..ed7b1e29b 100644 --- a/cpu/simple/cpu.hh +++ b/cpu/simple/cpu.hh @@ -63,6 +63,8 @@ namespace Trace { class SimpleCPU : public BaseCPU { + protected: + typedef TheISA::MachInst MachInst; public: // main simulation loop (one cycle) void tick(); @@ -173,7 +175,7 @@ class SimpleCPU : public BaseCPU // the next switchover Sampler *sampler; - StaticInstPtr<TheISA> curStaticInst; + StaticInstPtr curStaticInst; class CacheCompletionEvent : public Event { @@ -270,47 +272,47 @@ class SimpleCPU : public BaseCPU // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntReg(const StaticInst<TheISA> *si, int idx) + uint64_t readIntReg(const StaticInst *si, int idx) { return xc->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(const StaticInst<TheISA> *si, int idx) + float readFloatRegSingle(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegSingle(reg_idx); } - double readFloatRegDouble(const StaticInst<TheISA> *si, int idx) + double readFloatRegDouble(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegDouble(reg_idx); } - uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx) + uint64_t readFloatRegInt(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegInt(reg_idx); } - void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val) + void setIntReg(const StaticInst *si, int idx, uint64_t val) { xc->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val) + void setFloatRegSingle(const StaticInst *si, int idx, float val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegSingle(reg_idx, val); } - void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val) + void setFloatRegDouble(const StaticInst *si, int idx, double val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegDouble(reg_idx, val); } - void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val) + void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegInt(reg_idx, val); diff --git a/cpu/static_inst.cc b/cpu/static_inst.cc index 54bd9914e..c307dc6fc 100644 --- a/cpu/static_inst.cc +++ b/cpu/static_inst.cc @@ -30,19 +30,13 @@ #include "cpu/static_inst.hh" #include "sim/root.hh" -template <class ISA> -StaticInstPtr<ISA> StaticInst<ISA>::nullStaticInstPtr; - -template <class ISA> -typename StaticInst<ISA>::DecodeCache StaticInst<ISA>::decodeCache; +StaticInstPtr StaticInst::nullStaticInstPtr; // Define the decode cache hash map. -template StaticInst<AlphaISA>::DecodeCache -StaticInst<AlphaISA>::decodeCache; +StaticInst::DecodeCache StaticInst::decodeCache; -template <class ISA> void -StaticInst<ISA>::dumpDecodeCacheStats() +StaticInst::dumpDecodeCacheStats() { using namespace std; @@ -62,13 +56,8 @@ StaticInst<ISA>::dumpDecodeCacheStats() } } - -template StaticInstPtr<AlphaISA> -StaticInst<AlphaISA>::nullStaticInstPtr; - -template <class ISA> bool -StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const +StaticInst::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const { if (isDirectCtrl()) { tgt = branchTarget(pc); @@ -83,6 +72,3 @@ StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const return false; } - -// force instantiation of template function(s) above -template class StaticInst<AlphaISA>; diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 24997eadc..5106dcf06 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -113,6 +113,8 @@ class StaticInstBase : public RefCounted IsSerializing, ///< Serializes pipeline: won't execute until all /// older instructions have committed. + IsSerializeBefore, + IsSerializeAfter, IsMemBarrier, ///< Is a memory barrier IsWriteBarrier, ///< Is a write barrier @@ -196,7 +198,11 @@ class StaticInstBase : public RefCounted bool isUncondCtrl() const { return flags[IsUncondControl]; } bool isThreadSync() const { return flags[IsThreadSync]; } - bool isSerializing() const { return flags[IsSerializing]; } + bool isSerializing() const { return flags[IsSerializing] || + flags[IsSerializeBefore] || + flags[IsSerializeAfter]; } + bool isSerializeBefore() const { return flags[IsSerializeBefore]; } + bool isSerializeAfter() const { return flags[IsSerializeAfter]; } bool isMemBarrier() const { return flags[IsMemBarrier]; } bool isWriteBarrier() const { return flags[IsWriteBarrier]; } bool isNonSpeculative() const { return flags[IsNonSpeculative]; } @@ -208,7 +214,6 @@ class StaticInstBase : public RefCounted // forward declaration -template <class ISA> class StaticInstPtr; /** @@ -218,21 +223,18 @@ class StaticInstPtr; * that are generic across all ISAs but that differ in details * according to the specific ISA being used. */ -template <class ISA> class StaticInst : public StaticInstBase { public: /// Binary machine instruction type. - typedef typename ISA::MachInst MachInst; - /// Memory address type. - typedef typename ISA::Addr Addr; + typedef TheISA::MachInst MachInst; /// Logical register index type. - typedef typename ISA::RegIndex RegIndex; + typedef TheISA::RegIndex RegIndex; enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; @@ -247,7 +249,7 @@ class StaticInst : public StaticInstBase /// Pointer to a statically allocated "null" instruction object. /// Used to give eaCompInst() and memAccInst() something to return /// when called on non-memory instructions. - static StaticInstPtr<ISA> nullStaticInstPtr; + static StaticInstPtr nullStaticInstPtr; /** * Memory references only: returns "fake" instruction representing @@ -256,7 +258,7 @@ class StaticInst : public StaticInstBase * just the EA computation. */ virtual const - StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; } + StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; } /** * Memory references only: returns "fake" instruction representing @@ -265,7 +267,7 @@ class StaticInst : public StaticInstBase * just the memory access (not the EA computation). */ virtual const - StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; } + StaticInstPtr &memAccInst() const { return nullStaticInstPtr; } /// The binary machine instruction. const MachInst machInst; @@ -364,7 +366,7 @@ class StaticInst : public StaticInstBase /// Decoded instruction cache type. /// For now we're using a generic hash_map; this seems to work /// pretty well. - typedef m5::hash_map<MachInst, StaticInstPtr<ISA> > DecodeCache; + typedef m5::hash_map<MachInst, StaticInstPtr> DecodeCache; /// A cache of decoded instruction objects. static DecodeCache decodeCache; @@ -378,63 +380,40 @@ class StaticInst : public StaticInstBase /// Decode a machine instruction. /// @param mach_inst The binary instruction to decode. /// @retval A pointer to the corresponding StaticInst object. - static - StaticInstPtr<ISA> decode(MachInst mach_inst) - { -#ifdef DECODE_CACHE_HASH_STATS - // Simple stats on decode hash_map. Turns out the default - // hash function is as good as anything I could come up with. - const int dump_every_n = 10000000; - static int decodes_til_dump = dump_every_n; - - if (--decodes_til_dump == 0) { - dumpDecodeCacheStats(); - decodes_til_dump = dump_every_n; - } -#endif - - typename DecodeCache::iterator iter = decodeCache.find(mach_inst); - if (iter != decodeCache.end()) { - return iter->second; - } - - StaticInstPtr<ISA> si = ISA::decodeInst(mach_inst); - decodeCache[mach_inst] = si; - return si; - } + //This is defined as inline below. + static StaticInstPtr decode(MachInst mach_inst); }; typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr; /// Reference-counted pointer to a StaticInst object. -/// This type should be used instead of "StaticInst<ISA> *" so that +/// This type should be used instead of "StaticInst *" so that /// StaticInst objects can be properly reference-counted. -template <class ISA> -class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> > +class StaticInstPtr : public RefCountingPtr<StaticInst> { public: /// Constructor. StaticInstPtr() - : RefCountingPtr<StaticInst<ISA> >() + : RefCountingPtr<StaticInst>() { } - /// Conversion from "StaticInst<ISA> *". - StaticInstPtr(StaticInst<ISA> *p) - : RefCountingPtr<StaticInst<ISA> >(p) + /// Conversion from "StaticInst *". + StaticInstPtr(StaticInst *p) + : RefCountingPtr<StaticInst>(p) { } /// Copy constructor. StaticInstPtr(const StaticInstPtr &r) - : RefCountingPtr<StaticInst<ISA> >(r) + : RefCountingPtr<StaticInst>(r) { } /// Construct directly from machine instruction. - /// Calls StaticInst<ISA>::decode(). - StaticInstPtr(typename ISA::MachInst mach_inst) - : RefCountingPtr<StaticInst<ISA> >(StaticInst<ISA>::decode(mach_inst)) + /// Calls StaticInst::decode(). + StaticInstPtr(TheISA::MachInst mach_inst) + : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst)) { } @@ -445,4 +424,29 @@ class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> > } }; +inline StaticInstPtr +StaticInst::decode(StaticInst::MachInst mach_inst) +{ +#ifdef DECODE_CACHE_HASH_STATS + // Simple stats on decode hash_map. Turns out the default + // hash function is as good as anything I could come up with. + const int dump_every_n = 10000000; + static int decodes_til_dump = dump_every_n; + + if (--decodes_til_dump == 0) { + dumpDecodeCacheStats(); + decodes_til_dump = dump_every_n; + } +#endif + + DecodeCache::iterator iter = decodeCache.find(mach_inst); + if (iter != decodeCache.end()) { + return iter->second; + } + + StaticInstPtr si = TheISA::decodeInst(mach_inst); + decodeCache[mach_inst] = si; + return si; +} + #endif // __CPU_STATIC_INST_HH__ diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh index faec73138..a16a08085 100644 --- a/cpu/trace/reader/itx_reader.hh +++ b/cpu/trace/reader/itx_reader.hh @@ -46,6 +46,7 @@ */ class ITXReader : public MemTraceReader { + private: /** Trace file. */ FILE *trace; diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index a520e7ea9..2e8bbd1dd 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -53,6 +53,7 @@ #include "sim/system.hh" using namespace std; +using namespace AlphaISA; AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d, System *s, BaseCPU *c, Platform *p, @@ -181,10 +182,10 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data) } break; default: - return Machine_Check_Fault; + return MachineCheckFault; } - return No_Fault; + return NoFault; } Fault @@ -201,7 +202,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data) val = *(uint64_t *)data; break; default: - return Machine_Check_Fault; + return MachineCheckFault; } Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); @@ -251,7 +252,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data) panic("Unknown 64bit access, %#x\n", daddr); } - return No_Fault; + return NoFault; } Tick diff --git a/dev/baddev.cc b/dev/baddev.cc index 52c538707..87d683a5d 100644 --- a/dev/baddev.cc +++ b/dev/baddev.cc @@ -46,6 +46,7 @@ #include "sim/system.hh" using namespace std; +using namespace TheISA; BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu, HierParams *hier, Bus *pio_bus, const string &devicename) @@ -66,14 +67,14 @@ BadDevice::read(MemReqPtr &req, uint8_t *data) { panic("Device %s not imlpmented\n", devname); - return No_Fault; + return NoFault; } Fault BadDevice::write(MemReqPtr &req, const uint8_t *data) { panic("Device %s not imlpmented\n", devname); - return No_Fault; + return NoFault; } Tick diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index 1279efc82..56682a224 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -48,6 +48,7 @@ #include "sim/sim_object.hh" using namespace std; +using namespace TheISA; //// // Initialization and destruction @@ -401,7 +402,7 @@ IdeController::read(MemReqPtr &req, uint8_t *data) parseAddr(req->paddr, offset, channel, reg_type); if (!io_enabled) - return No_Fault; + return NoFault; switch (reg_type) { case BMI_BLOCK: @@ -457,7 +458,7 @@ IdeController::read(MemReqPtr &req, uint8_t *data) DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", offset, req->size, *(uint32_t*)data); - return No_Fault; + return NoFault; } Fault @@ -472,12 +473,12 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) parseAddr(req->paddr, offset, channel, reg_type); if (!io_enabled) - return No_Fault; + return NoFault; switch (reg_type) { case BMI_BLOCK: if (!bm_enabled) - return No_Fault; + return NoFault; switch (offset) { // Bus master IDE command register @@ -627,7 +628,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", offset, req->size, *(uint32_t*)data); - return No_Fault; + return NoFault; } //// diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index 9d8bb8825..41400c590 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -53,6 +53,7 @@ #include "arch/isa_traits.hh" using namespace std; +using namespace TheISA; IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, int id, Tick delay) diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc index e2802eaa9..2afebbded 100644 --- a/dev/isa_fake.cc +++ b/dev/isa_fake.cc @@ -45,6 +45,7 @@ #include "sim/system.hh" using namespace std; +using namespace TheISA; IsaFake::IsaFake(const string &name, Addr a, MemoryController *mmu, HierParams *hier, Bus *pio_bus, Addr size) @@ -73,23 +74,23 @@ IsaFake::read(MemReqPtr &req, uint8_t *data) case sizeof(uint64_t): *(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL; - return No_Fault; + return NoFault; case sizeof(uint32_t): *(uint32_t*)data = 0xFFFFFFFF; - return No_Fault; + return NoFault; case sizeof(uint16_t): *(uint16_t*)data = 0xFFFF; - return No_Fault; + return NoFault; case sizeof(uint8_t): *(uint8_t*)data = 0xFF; - return No_Fault; + return NoFault; default: panic("invalid access size(?) for PCI configspace!\n"); } DPRINTFN("Isa FakeSMC ERROR: read daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; } Fault @@ -100,7 +101,7 @@ IsaFake::write(MemReqPtr &req, const uint8_t *data) //:Addr daddr = (req->paddr & addr_mask) >> 6; - return No_Fault; + return NoFault; } Tick diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index 9010850ab..4b08d8497 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -84,6 +84,7 @@ const char *NsDmaState[] = using namespace std; using namespace Net; +using namespace TheISA; /////////////////////////////////////////////////////////////////////// // @@ -130,8 +131,6 @@ NSGigE::NSGigE(Params *p) } else if (p->payload_bus) panic("Must define a header bus if defining a payload bus"); - pioDelayWrite = p->pio_delay_write && pioInterface; - intrDelay = p->intr_delay; dmaReadDelay = p->dma_read_delay; dmaWriteDelay = p->dma_write_delay; @@ -575,14 +574,14 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { readConfig(daddr & 0xff, req->size, data); - return No_Fault; + return NoFault; } else if (daddr >= MIB_START && daddr <= MIB_END) { // don't implement all the MIB's. hopefully the kernel // doesn't actually DEPEND upon their values // MIB are just hardware stats keepers uint32_t ® = *(uint32_t *) data; reg = 0; - return No_Fault; + return NoFault; } else if (daddr > 0x3FC) panic("Something is messed up!\n"); @@ -784,7 +783,7 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) daddr, req->size); } - return No_Fault; + return NoFault; } Fault @@ -800,17 +799,10 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { writeConfig(daddr & 0xff, req->size, data); - return No_Fault; + return NoFault; } else if (daddr > 0x3FC) panic("Something is messed up!\n"); - if (pioDelayWrite) { - int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; - if (cpu >= writeQueue.size()) - writeQueue.resize(cpu + 1); - writeQueue[cpu].push_back(RegWriteData(daddr, *(uint32_t *)data)); - } - if (req->size == sizeof(uint32_t)) { uint32_t reg = *(uint32_t *)data; uint16_t rfaddr; @@ -823,24 +815,20 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (reg & CR_TXD) { txEnable = false; } else if (reg & CR_TXE) { - if (!pioDelayWrite) { - txEnable = true; + txEnable = true; - // the kernel is enabling the transmit machine - if (txState == txIdle) - txKick(); - } + // the kernel is enabling the transmit machine + if (txState == txIdle) + txKick(); } if (reg & CR_RXD) { rxEnable = false; } else if (reg & CR_RXE) { - if (!pioDelayWrite) { - rxEnable = true; + rxEnable = true; - if (rxState == rxIdle) - rxKick(); - } + if (rxState == rxIdle) + rxKick(); } if (reg & CR_TXR) @@ -1203,7 +1191,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) panic("Invalid Request Size"); } - return No_Fault; + return NoFault; } void @@ -2948,38 +2936,9 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) Tick NSGigE::cacheAccess(MemReqPtr &req) { - Addr daddr = req->paddr & 0xfff; DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", - req->paddr, daddr); - - if (!pioDelayWrite || !req->cmd.isWrite()) - return curTick + pioLatency; - - int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; - std::list<RegWriteData> &wq = writeQueue[cpu]; - if (wq.empty()) - panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr); - - const RegWriteData &data = wq.front(); - if (data.daddr != daddr) - panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x", - cpu, data.daddr, daddr); - - if (daddr == CR) { - if ((data.value & (CR_TXD | CR_TXE)) == CR_TXE) { - txEnable = true; - if (txState == txIdle) - txKick(); - } - - if ((data.value & (CR_RXD | CR_RXE)) == CR_RXE) { - rxEnable = true; - if (rxState == rxIdle) - rxKick(); - } - } + req->paddr, req->paddr & 0xfff); - wq.pop_front(); return curTick + pioLatency; } @@ -3039,7 +2998,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) Param<Tick> dma_write_factor; Param<bool> dma_no_allocate; Param<Tick> pio_latency; - Param<bool> pio_delay_write; Param<Tick> intr_delay; Param<Tick> rx_delay; @@ -3080,7 +3038,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM(dma_write_factor, "multiplier for dma writes"), INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), - INIT_PARAM(pio_delay_write, ""), INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), INIT_PARAM(rx_delay, "Receive Delay"), @@ -3125,7 +3082,6 @@ CREATE_SIM_OBJECT(NSGigE) params->dma_write_factor = dma_write_factor; params->dma_no_allocate = dma_no_allocate; params->pio_latency = pio_latency; - params->pio_delay_write = pio_delay_write; params->intr_delay = intr_delay; params->rx_delay = rx_delay; diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh index ade7e32e6..cdd8e4b9e 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -170,9 +170,6 @@ class NSGigE : public PciDev static const Addr size = sizeof(dp_regs); protected: - typedef std::deque<PacketPtr> pktbuf_t; - typedef pktbuf_t::iterator pktiter_t; - /** device register file */ dp_regs regs; dp_rom rom; @@ -239,15 +236,6 @@ class NSGigE : public PciDev uint32_t rxDescCnt; DmaState rxDmaState; - struct RegWriteData { - Addr daddr; - uint32_t value; - RegWriteData(Addr da, uint32_t val) : daddr(da), value(val) {} - }; - - std::vector<std::list<RegWriteData> > writeQueue; - bool pioDelayWrite; - bool extstsEnable; /** EEPROM State Machine */ @@ -385,7 +373,6 @@ class NSGigE : public PciDev Tick tx_delay; Tick rx_delay; Tick pio_latency; - bool pio_delay_write; bool dma_desc_free; bool dma_data_free; Tick dma_read_delay; diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index 396e130af..d55084fa5 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -47,6 +47,7 @@ #include "sim/system.hh" using namespace std; +using namespace TheISA; PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu, @@ -112,16 +113,16 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data) switch (req->size) { // case sizeof(uint64_t): // *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF; - // return No_Fault; + // return NoFault; case sizeof(uint32_t): *(uint32_t*)data = 0xFFFFFFFF; - return No_Fault; + return NoFault; case sizeof(uint16_t): *(uint16_t*)data = 0xFFFF; - return No_Fault; + return NoFault; case sizeof(uint8_t): *(uint8_t*)data = 0xFF; - return No_Fault; + return NoFault; default: panic("invalid access size(?) for PCI configspace!\n"); } @@ -131,7 +132,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data) case sizeof(uint16_t): case sizeof(uint8_t): devices[device][func]->readConfig(reg, req->size, data); - return No_Fault; + return NoFault; default: panic("invalid access size(?) for PCI configspace!\n"); } @@ -140,7 +141,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data) DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; } Fault @@ -164,7 +165,7 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data) devices[device][func]->writeConfig(reg, req->size, data); - return No_Fault; + return NoFault; } void diff --git a/dev/pcidev.cc b/dev/pcidev.cc index 1d9ea137d..a05ee3803 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -72,11 +72,11 @@ PciDev::PciDev(Params *p) Fault PciDev::read(MemReqPtr &req, uint8_t *data) -{ return No_Fault; } +{ return NoFault; } Fault PciDev::write(MemReqPtr &req, const uint8_t *data) -{ return No_Fault; } +{ return NoFault; } Fault PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) diff --git a/dev/pcidev.hh b/dev/pcidev.hh index efc805b3f..9427463bf 100644 --- a/dev/pcidev.hh +++ b/dev/pcidev.hh @@ -272,7 +272,7 @@ PciDev::readBar(MemReqPtr &req, uint8_t *data) return readBar4(req, req->paddr - BARAddrs[4], data); if (isBAR(req->paddr, 5)) return readBar5(req, req->paddr - BARAddrs[5], data); - return Machine_Check_Fault; + return MachineCheckFault; } inline Fault @@ -290,7 +290,7 @@ PciDev::writeBar(MemReqPtr &req, const uint8_t *data) return writeBar4(req, req->paddr - BARAddrs[4], data); if (isBAR(req->paddr, 5)) return writeBar5(req, req->paddr - BARAddrs[5], data); - return Machine_Check_Fault; + return MachineCheckFault; } #endif // __DEV_PCIDEV_HH__ diff --git a/dev/platform.cc b/dev/platform.cc index 58f94db7b..5b667b12c 100644 --- a/dev/platform.cc +++ b/dev/platform.cc @@ -31,6 +31,7 @@ #include "sim/sim_exit.hh" using namespace std; +using namespace TheISA; Platform::Platform(const string &name, IntrControl *intctrl, PciConfigAll *pci) : SimObject(name), intrctrl(intctrl), pciconfig(pci) diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh index 6560e15c2..57f81c5a9 100644 --- a/dev/simple_disk.hh +++ b/dev/simple_disk.hh @@ -44,19 +44,19 @@ class PhysicalMemory; */ class SimpleDisk : public SimObject { -public: - typedef uint64_t baddr_t; + public: + typedef uint64_t baddr_t; -protected: - PhysicalMemory *physmem; - DiskImage *image; + protected: + PhysicalMemory *physmem; + DiskImage *image; -public: - SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img); - ~SimpleDisk(); + public: + SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img); + ~SimpleDisk(); - void read(Addr addr, baddr_t block, int count) const; - void write(Addr addr, baddr_t block, int count); + void read(Addr addr, baddr_t block, int count) const; + void write(Addr addr, baddr_t block, int count); }; #endif // __DEV_SIMPLE_DISK_HH__ diff --git a/dev/sinic.cc b/dev/sinic.cc index 69239df32..c499d2f49 100644 --- a/dev/sinic.cc +++ b/dev/sinic.cc @@ -50,6 +50,7 @@ #include "targetarch/vtophys.hh" using namespace Net; +using namespace TheISA; namespace Sinic { @@ -112,8 +113,6 @@ Device::Device(Params *p) p->dma_no_allocate); } else if (p->payload_bus) panic("must define a header bus if defining a payload bus"); - - pioDelayWrite = p->pio_delay_write && pioInterface; } Device::~Device() @@ -352,9 +351,6 @@ Device::prepareRead(int cpu, int index) void Device::prepareWrite(int cpu, int index) { - if (cpu >= writeQueue.size()) - writeQueue.resize(cpu + 1); - prepareIO(cpu, index); } @@ -367,11 +363,11 @@ Device::read(MemReqPtr &req, uint8_t *data) assert(config.command & PCI_CMD_MSE); Fault fault = readBar(req, data); - if (fault == Machine_Check_Fault) { + if (fault == MachineCheckFault) { panic("address does not map to a BAR pa=%#x va=%#x size=%d", req->paddr, req->vaddr, req->size); - return Machine_Check_Fault; + return MachineCheckFault; } return fault; @@ -421,7 +417,7 @@ Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) if (raddr == Regs::IntrStatus) devIntrClear(); - return No_Fault; + return NoFault; } /** @@ -451,7 +447,7 @@ Device::iprRead(Addr daddr, int cpu, uint64_t &result) DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n", info.name, cpu, result); - return No_Fault; + return NoFault; } /** @@ -463,11 +459,11 @@ Device::write(MemReqPtr &req, const uint8_t *data) assert(config.command & PCI_CMD_MSE); Fault fault = writeBar(req, data); - if (fault == Machine_Check_Fault) { + if (fault == MachineCheckFault) { panic("address does not map to a BAR pa=%#x va=%#x size=%d", req->paddr, req->vaddr, req->size); - return Machine_Check_Fault; + return MachineCheckFault; } return fault; @@ -493,22 +489,18 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) panic("invalid size for %s: cpu=%d da=%#x pa=%#x va=%#x size=%d", info.name, cpu, daddr, req->paddr, req->vaddr, req->size); - uint32_t reg32 = *(uint32_t *)data; + //uint32_t reg32 = *(uint32_t *)data; uint64_t reg64 = *(uint64_t *)data; DPRINTF(EthernetPIO, "write %s: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n", - info.name, cpu, info.size == 4 ? reg32 : reg64, daddr, + info.name, cpu, info.size == 4 ? (*(uint32_t *)data) : reg64, daddr, req->paddr, req->vaddr, req->size); prepareWrite(cpu, index); - if (pioDelayWrite) - writeQueue[cpu].push_back(RegWriteData(daddr, reg64)); + regWrite(daddr, cpu, data); - if (!pioDelayWrite || !info.delay_write) - regWrite(daddr, cpu, data); - - return No_Fault; + return NoFault; } void @@ -1570,27 +1562,6 @@ Device::cacheAccess(MemReqPtr &req) DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n", req->cmd.toString(), req->paddr, bar, daddr); - if (!pioDelayWrite || !req->cmd.isWrite()) - return curTick + pioLatency; - - if (bar == 0) { - int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; - std::list<RegWriteData> &wq = writeQueue[cpu]; - if (wq.empty()) - panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr); - - const RegWriteData &data = wq.front(); - if (data.daddr != daddr) - panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x", - cpu, data.daddr, daddr); - - const Regs::Info &info = regInfo(data.daddr); - if (info.delay_write) - regWrite(daddr, cpu, (uint8_t *)&data.value); - - wq.pop_front(); - } - return curTick + pioLatency; } @@ -1648,7 +1619,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) Param<Tick> dma_write_factor; Param<bool> dma_no_allocate; Param<Tick> pio_latency; - Param<bool> pio_delay_write; Param<Tick> intr_delay; Param<Tick> rx_delay; @@ -1692,7 +1662,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device) INIT_PARAM(dma_write_factor, "multiplier for dma writes"), INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"), INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), - INIT_PARAM(pio_delay_write, ""), INIT_PARAM(intr_delay, "Interrupt Delay"), INIT_PARAM(rx_delay, "Receive Delay"), @@ -1740,7 +1709,6 @@ CREATE_SIM_OBJECT(Device) params->dma_write_factor = dma_write_factor; params->dma_no_allocate = dma_no_allocate; params->pio_latency = pio_latency; - params->pio_delay_write = pio_delay_write; params->intr_delay = intr_delay; params->tx_delay = tx_delay; diff --git a/dev/sinic.hh b/dev/sinic.hh index af2f109a4..97ebf4c30 100644 --- a/dev/sinic.hh +++ b/dev/sinic.hh @@ -283,17 +283,6 @@ class Device : public Base void regWrite(Addr daddr, int cpu, const uint8_t *data); Tick cacheAccess(MemReqPtr &req); - protected: - struct RegWriteData { - Addr daddr; - uint64_t value; - RegWriteData(Addr da, uint64_t val) : daddr(da), value(val) {} - }; - - std::vector<std::list<RegWriteData> > writeQueue; - - bool pioDelayWrite; - /** * Statistics */ @@ -349,7 +338,6 @@ class Device : public Base Bus *header_bus; Bus *payload_bus; Tick pio_latency; - bool pio_delay_write; PhysicalMemory *physmem; IntrControl *intctrl; bool rx_filter; diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh index b7008b4e1..fc1f4c06b 100644 --- a/dev/sinicreg.hh +++ b/dev/sinicreg.hh @@ -157,8 +157,6 @@ struct Info uint8_t size; bool read; bool write; - bool delay_read; - bool delay_write; const char *name; }; @@ -167,33 +165,33 @@ struct Info inline const Regs::Info& regInfo(Addr daddr) { - static Regs::Info invalid = { 0, false, false, false, false, "invalid" }; + static Regs::Info invalid = { 0, false, false, "invalid" }; static Regs::Info info [] = { - { 4, true, true, false, false, "Config" }, - { 4, false, true, false, false, "Command" }, - { 4, true, true, false, false, "IntrStatus" }, - { 4, true, true, false, false, "IntrMask" }, - { 4, true, false, false, false, "RxMaxCopy" }, - { 4, true, false, false, false, "TxMaxCopy" }, - { 4, true, false, false, false, "RxMaxIntr" }, + { 4, true, true, "Config" }, + { 4, false, true, "Command" }, + { 4, true, true, "IntrStatus" }, + { 4, true, true, "IntrMask" }, + { 4, true, false, "RxMaxCopy" }, + { 4, true, false, "TxMaxCopy" }, + { 4, true, false, "RxMaxIntr" }, invalid, - { 4, true, false, false, false, "RxFifoSize" }, - { 4, true, false, false, false, "TxFifoSize" }, - { 4, true, false, false, false, "RxFifoMark" }, - { 4, true, false, false, false, "TxFifoMark" }, - { 8, true, true, false, true, "RxData" }, + { 4, true, false, "RxFifoSize" }, + { 4, true, false, "TxFifoSize" }, + { 4, true, false, "RxFifoMark" }, + { 4, true, false, "TxFifoMark" }, + { 8, true, true, "RxData" }, invalid, - { 8, true, false, false, false, "RxDone" }, + { 8, true, false, "RxDone" }, invalid, - { 8, true, false, false, false, "RxWait" }, + { 8, true, false, "RxWait" }, invalid, - { 8, true, true, false, true, "TxData" }, + { 8, true, true, "TxData" }, invalid, - { 8, true, false, false, false, "TxDone" }, + { 8, true, false, "TxDone" }, invalid, - { 8, true, false, false, false, "TxWait" }, + { 8, true, false, "TxWait" }, invalid, - { 8, true, false, false, false, "HwAddr" }, + { 8, true, false, "HwAddr" }, invalid, }; diff --git a/dev/tsunami.cc b/dev/tsunami.cc index 760848a00..58fc7434e 100644 --- a/dev/tsunami.cc +++ b/dev/tsunami.cc @@ -46,6 +46,8 @@ #include "sim/system.hh" using namespace std; +//Should this be AlphaISA? +using namespace TheISA; Tsunami::Tsunami(const string &name, System *s, IntrControl *ic, PciConfigAll *pci) diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc index 2287a2a3d..4dc4413a1 100644 --- a/dev/tsunami_cchip.cc +++ b/dev/tsunami_cchip.cc @@ -47,6 +47,8 @@ #include "sim/system.hh" using namespace std; +//Should this be AlphaISA? +using namespace TheISA; TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, MemoryController *mmu, HierParams *hier, @@ -92,81 +94,81 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) if (daddr & TSDEV_CC_BDIMS) { *(uint64_t*)data = dim[(daddr >> 4) & 0x3F]; - return No_Fault; + return NoFault; } if (daddr & TSDEV_CC_BDIRS) { *(uint64_t*)data = dir[(daddr >> 4) & 0x3F]; - return No_Fault; + return NoFault; } switch(regnum) { case TSDEV_CC_CSR: *(uint64_t*)data = 0x0; - return No_Fault; + return NoFault; case TSDEV_CC_MTR: panic("TSDEV_CC_MTR not implemeted\n"); - return No_Fault; + return NoFault; case TSDEV_CC_MISC: *(uint64_t*)data = (ipint << 8) & 0xF | (itint << 4) & 0xF | (xc->cpu_id & 0x3); - return No_Fault; + return NoFault; case TSDEV_CC_AAR0: case TSDEV_CC_AAR1: case TSDEV_CC_AAR2: case TSDEV_CC_AAR3: *(uint64_t*)data = 0; - return No_Fault; + return NoFault; case TSDEV_CC_DIM0: *(uint64_t*)data = dim[0]; - return No_Fault; + return NoFault; case TSDEV_CC_DIM1: *(uint64_t*)data = dim[1]; - return No_Fault; + return NoFault; case TSDEV_CC_DIM2: *(uint64_t*)data = dim[2]; - return No_Fault; + return NoFault; case TSDEV_CC_DIM3: *(uint64_t*)data = dim[3]; - return No_Fault; + return NoFault; case TSDEV_CC_DIR0: *(uint64_t*)data = dir[0]; - return No_Fault; + return NoFault; case TSDEV_CC_DIR1: *(uint64_t*)data = dir[1]; - return No_Fault; + return NoFault; case TSDEV_CC_DIR2: *(uint64_t*)data = dir[2]; - return No_Fault; + return NoFault; case TSDEV_CC_DIR3: *(uint64_t*)data = dir[3]; - return No_Fault; + return NoFault; case TSDEV_CC_DRIR: *(uint64_t*)data = drir; - return No_Fault; + return NoFault; case TSDEV_CC_PRBEN: panic("TSDEV_CC_PRBEN not implemented\n"); - return No_Fault; + return NoFault; case TSDEV_CC_IIC0: case TSDEV_CC_IIC1: case TSDEV_CC_IIC2: case TSDEV_CC_IIC3: panic("TSDEV_CC_IICx not implemented\n"); - return No_Fault; + return NoFault; case TSDEV_CC_MPR0: case TSDEV_CC_MPR1: case TSDEV_CC_MPR2: case TSDEV_CC_MPR3: panic("TSDEV_CC_MPRx not implemented\n"); - return No_Fault; + return NoFault; case TSDEV_CC_IPIR: *(uint64_t*)data = ipint; - return No_Fault; + return NoFault; case TSDEV_CC_ITIR: *(uint64_t*)data = itint; - return No_Fault; + return NoFault; default: panic("default in cchip read reached, accessing 0x%x\n"); } // uint64_t @@ -179,7 +181,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) *(uint32_t*)data = drir; } else panic("invalid access size(?) for tsunami register!\n"); - return No_Fault; + return NoFault; case sizeof(uint16_t): case sizeof(uint8_t): default: @@ -187,7 +189,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) } DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size); - return No_Fault; + return NoFault; } Fault @@ -243,16 +245,16 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) } } - return No_Fault; + return NoFault; } switch(regnum) { case TSDEV_CC_CSR: panic("TSDEV_CC_CSR write\n"); - return No_Fault; + return NoFault; case TSDEV_CC_MTR: panic("TSDEV_CC_MTR write not implemented\n"); - return No_Fault; + return NoFault; case TSDEV_CC_MISC: uint64_t ipreq; ipreq = (*(uint64_t*)data >> 12) & 0xF; @@ -285,13 +287,13 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n"); - return No_Fault; + return NoFault; case TSDEV_CC_AAR0: case TSDEV_CC_AAR1: case TSDEV_CC_AAR2: case TSDEV_CC_AAR3: panic("TSDEV_CC_AARx write not implemeted\n"); - return No_Fault; + return NoFault; case TSDEV_CC_DIM0: case TSDEV_CC_DIM1: case TSDEV_CC_DIM2: @@ -341,7 +343,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) } } - return No_Fault; + return NoFault; case TSDEV_CC_DIR0: case TSDEV_CC_DIR1: case TSDEV_CC_DIR2: @@ -363,13 +365,13 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) panic("TSDEV_CC_MPRx write not implemented\n"); case TSDEV_CC_IPIR: clearIPI(*(uint64_t*)data); - return No_Fault; + return NoFault; case TSDEV_CC_ITIR: clearITI(*(uint64_t*)data); - return No_Fault; + return NoFault; case TSDEV_CC_IPIQ: reqIPI(*(uint64_t*)data); - return No_Fault; + return NoFault; default: panic("default in cchip read reached, accessing 0x%x\n"); } @@ -384,7 +386,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; } void diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc index 724a5bfb9..e66d6653b 100644 --- a/dev/tsunami_io.cc +++ b/dev/tsunami_io.cc @@ -50,6 +50,8 @@ #include "mem/functional/memory_control.hh" using namespace std; +//Should this be AlphaISA? +using namespace TheISA; TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i) : _name(name), event(t, i), addr(0) @@ -459,38 +461,38 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) // PIC1 mask read case TSDEV_PIC1_MASK: *(uint8_t*)data = ~mask1; - return No_Fault; + return NoFault; case TSDEV_PIC2_MASK: *(uint8_t*)data = ~mask2; - return No_Fault; + return NoFault; case TSDEV_PIC1_ISR: // !!! If this is modified 64bit case needs to be too // Pal code has to do a 64 bit physical read because there is // no load physical byte instruction *(uint8_t*)data = picr; - return No_Fault; + return NoFault; case TSDEV_PIC2_ISR: // PIC2 not implemnted... just return 0 *(uint8_t*)data = 0x00; - return No_Fault; + return NoFault; case TSDEV_TMR0_DATA: pitimer.counter0.read(data); - return No_Fault; + return NoFault; case TSDEV_TMR1_DATA: pitimer.counter1.read(data); - return No_Fault; + return NoFault; case TSDEV_TMR2_DATA: pitimer.counter2.read(data); - return No_Fault; + return NoFault; case TSDEV_RTC_DATA: rtc.readData(data); - return No_Fault; + return NoFault; case TSDEV_CTRL_PORTB: if (pitimer.counter2.outputHigh()) *data = PORTB_SPKR_HIGH; else *data = 0x00; - return No_Fault; + return NoFault; default: panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); } @@ -506,7 +508,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) // Pal code has to do a 64 bit physical read because there is // no load physical byte instruction *(uint64_t*)data = (uint64_t)picr; - return No_Fault; + return NoFault; default: panic("I/O Read - invalid size - va %#x size %d\n", req->vaddr, req->size); @@ -518,7 +520,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) } panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); - return No_Fault; + return NoFault; } Fault @@ -550,63 +552,63 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) tsunami->cchip->clearDRIR(55); DPRINTF(Tsunami, "clearing pic interrupt\n"); } - return No_Fault; + return NoFault; case TSDEV_PIC2_MASK: mask2 = *(uint8_t*)data; //PIC2 Not implemented to interrupt - return No_Fault; + return NoFault; case TSDEV_PIC1_ACK: // clear the interrupt on the PIC picr &= ~(1 << (*(uint8_t*)data & 0xF)); if (!(picr & mask1)) tsunami->cchip->clearDRIR(55); - return No_Fault; + return NoFault; case TSDEV_DMA1_CMND: - return No_Fault; + return NoFault; case TSDEV_DMA2_CMND: - return No_Fault; + return NoFault; case TSDEV_DMA1_MMASK: - return No_Fault; + return NoFault; case TSDEV_DMA2_MMASK: - return No_Fault; + return NoFault; case TSDEV_PIC2_ACK: - return No_Fault; + return NoFault; case TSDEV_DMA1_RESET: - return No_Fault; + return NoFault; case TSDEV_DMA2_RESET: - return No_Fault; + return NoFault; case TSDEV_DMA1_MODE: mode1 = *(uint8_t*)data; - return No_Fault; + return NoFault; case TSDEV_DMA2_MODE: mode2 = *(uint8_t*)data; - return No_Fault; + return NoFault; case TSDEV_DMA1_MASK: case TSDEV_DMA2_MASK: - return No_Fault; + return NoFault; case TSDEV_TMR0_DATA: pitimer.counter0.write(data); - return No_Fault; + return NoFault; case TSDEV_TMR1_DATA: pitimer.counter1.write(data); - return No_Fault; + return NoFault; case TSDEV_TMR2_DATA: pitimer.counter2.write(data); - return No_Fault; + return NoFault; case TSDEV_TMR_CTRL: pitimer.writeControl(data); - return No_Fault; + return NoFault; case TSDEV_RTC_ADDR: rtc.writeAddr(data); - return No_Fault; + return NoFault; case TSDEV_KBD: - return No_Fault; + return NoFault; case TSDEV_RTC_DATA: rtc.writeData(data); - return No_Fault; + return NoFault; case TSDEV_CTRL_PORTB: // System Control Port B not implemented - return No_Fault; + return NoFault; default: panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data); } @@ -619,7 +621,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) } - return No_Fault; + return NoFault; } void diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc index e61137170..46efc3dfe 100644 --- a/dev/tsunami_pchip.cc +++ b/dev/tsunami_pchip.cc @@ -47,6 +47,8 @@ #include "sim/system.hh" using namespace std; +//Should this be AlphaISA? +using namespace TheISA; TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, MemoryController *mmu, HierParams *hier, @@ -90,60 +92,60 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data) switch(daddr) { case TSDEV_PC_WSBA0: *(uint64_t*)data = wsba[0]; - return No_Fault; + return NoFault; case TSDEV_PC_WSBA1: *(uint64_t*)data = wsba[1]; - return No_Fault; + return NoFault; case TSDEV_PC_WSBA2: *(uint64_t*)data = wsba[2]; - return No_Fault; + return NoFault; case TSDEV_PC_WSBA3: *(uint64_t*)data = wsba[3]; - return No_Fault; + return NoFault; case TSDEV_PC_WSM0: *(uint64_t*)data = wsm[0]; - return No_Fault; + return NoFault; case TSDEV_PC_WSM1: *(uint64_t*)data = wsm[1]; - return No_Fault; + return NoFault; case TSDEV_PC_WSM2: *(uint64_t*)data = wsm[2]; - return No_Fault; + return NoFault; case TSDEV_PC_WSM3: *(uint64_t*)data = wsm[3]; - return No_Fault; + return NoFault; case TSDEV_PC_TBA0: *(uint64_t*)data = tba[0]; - return No_Fault; + return NoFault; case TSDEV_PC_TBA1: *(uint64_t*)data = tba[1]; - return No_Fault; + return NoFault; case TSDEV_PC_TBA2: *(uint64_t*)data = tba[2]; - return No_Fault; + return NoFault; case TSDEV_PC_TBA3: *(uint64_t*)data = tba[3]; - return No_Fault; + return NoFault; case TSDEV_PC_PCTL: *(uint64_t*)data = pctl; - return No_Fault; + return NoFault; case TSDEV_PC_PLAT: panic("PC_PLAT not implemented\n"); case TSDEV_PC_RES: panic("PC_RES not implemented\n"); case TSDEV_PC_PERROR: *(uint64_t*)data = 0x00; - return No_Fault; + return NoFault; case TSDEV_PC_PERRMASK: *(uint64_t*)data = 0x00; - return No_Fault; + return NoFault; case TSDEV_PC_PERRSET: panic("PC_PERRSET not implemented\n"); case TSDEV_PC_TLBIV: panic("PC_TLBIV not implemented\n"); case TSDEV_PC_TLBIA: *(uint64_t*)data = 0x00; // shouldn't be readable, but linux - return No_Fault; + return NoFault; case TSDEV_PC_PMONCTL: panic("PC_PMONCTL not implemented\n"); case TSDEV_PC_PMONCNT: @@ -162,7 +164,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data) } DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; } Fault @@ -179,49 +181,49 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) switch(daddr) { case TSDEV_PC_WSBA0: wsba[0] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSBA1: wsba[1] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSBA2: wsba[2] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSBA3: wsba[3] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSM0: wsm[0] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSM1: wsm[1] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSM2: wsm[2] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_WSM3: wsm[3] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_TBA0: tba[0] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_TBA1: tba[1] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_TBA2: tba[2] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_TBA3: tba[3] = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_PCTL: pctl = *(uint64_t*)data; - return No_Fault; + return NoFault; case TSDEV_PC_PLAT: panic("PC_PLAT not implemented\n"); case TSDEV_PC_RES: panic("PC_RES not implemented\n"); case TSDEV_PC_PERROR: - return No_Fault; + return NoFault; case TSDEV_PC_PERRMASK: panic("PC_PERRMASK not implemented\n"); case TSDEV_PC_PERRSET: @@ -229,7 +231,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) case TSDEV_PC_TLBIV: panic("PC_TLBIV not implemented\n"); case TSDEV_PC_TLBIA: - return No_Fault; // value ignored, supposted to invalidate SG TLB + return NoFault; // value ignored, supposted to invalidate SG TLB case TSDEV_PC_PMONCTL: panic("PC_PMONCTL not implemented\n"); case TSDEV_PC_PMONCNT: @@ -249,7 +251,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; } #define DMA_ADDR_MASK ULL(0x3ffffffff) diff --git a/dev/uart8250.cc b/dev/uart8250.cc index 71f429069..65bccee86 100644 --- a/dev/uart8250.cc +++ b/dev/uart8250.cc @@ -46,6 +46,7 @@ #include "sim/builder.hh" using namespace std; +using namespace TheISA; Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit) : Event(&mainEventQueue), uart(u) @@ -183,7 +184,7 @@ Uart8250::read(MemReqPtr &req, uint8_t *data) break; } - return No_Fault; + return NoFault; } @@ -255,7 +256,7 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data) panic("Tried to access a UART port that doesn't exist\n"); break; } - return No_Fault; + return NoFault; } void diff --git a/kern/freebsd/freebsd_system.cc b/kern/freebsd/freebsd_system.cc index dbf60a3fc..cead8caaf 100644 --- a/kern/freebsd/freebsd_system.cc +++ b/kern/freebsd/freebsd_system.cc @@ -46,6 +46,7 @@ #define TIMER_FREQUENCY 1193180 using namespace std; +using namespace TheISA; FreebsdSystem::FreebsdSystem(Params *p) : System(p) diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc index 3a7d12443..50bbaee00 100644 --- a/kern/kernel_stats.cc +++ b/kern/kernel_stats.cc @@ -137,14 +137,14 @@ Statistics::regStats(const string &_name) } _faults - .init(Num_Faults) + .init(NumFaults) .name(name() + ".faults") .desc("number of faults") .flags(total | pdf | nozero | nonan) ; - for (int i = 1; i < Num_Faults; ++i) { - const char *str = FaultName(i); + for (int i = 1; i < NumFaults; ++i) { + const char *str = (*ListOfFaults[i])->name; if (str) _faults.subname(i, str); } diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh index 62dd84a28..02d78e4d9 100644 --- a/kern/kernel_stats.hh +++ b/kern/kernel_stats.hh @@ -41,7 +41,6 @@ class ExecContext; class FnEvent; // What does kernel stats expect is included? class System; -enum Fault; namespace Kernel { @@ -106,7 +105,7 @@ class Binning cpu_mode themode; void palSwapContext(ExecContext *xc); - void execute(ExecContext *xc, StaticInstPtr<TheISA> inst); + void execute(ExecContext *xc, StaticInstPtr inst); void call(ExecContext *xc, Stats::MainBin *myBin); void changeMode(cpu_mode mode); @@ -124,6 +123,7 @@ class Binning class Statistics : public Serializable { + private: friend class Binning; private: @@ -176,7 +176,13 @@ class Statistics : public Serializable void ivlb() { _ivlb++; } void ivle() { _ivle++; } void hwrei() { _hwrei++; } - void fault(Fault fault) { _faults[fault]++; } + void fault(Fault fault) + { + if(fault == NoFault) _faults[0]++; + else if(fault == MachineCheckFault) _faults[2]++; + else if(fault == AlignmentFault) _faults[7]++; + else _faults[fault->id]++; + }// FIXME: When there are no generic system fault objects, this will go back to _faults[fault]++; } void swpipl(int ipl); void mode(cpu_mode newmode); void context(Addr oldpcbb, Addr newpcbb); diff --git a/kern/linux/linux.hh b/kern/linux/linux.hh index b083b5a31..0dbccf546 100644 --- a/kern/linux/linux.hh +++ b/kern/linux/linux.hh @@ -28,7 +28,314 @@ #ifndef __LINUX_HH__ #define __LINUX_HH__ +#include "config/full_system.hh" + +#if FULL_SYSTEM class Linux {}; +#else //!FULL_SYSTEM + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> // for host open() flags +#include <string.h> // for memset() +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "sim/syscall_emul.hh" + +/// +/// This class encapsulates the types, structures, constants, +/// functions, and syscall-number mappings specific to the Alpha Linux +/// syscall interface. +/// +class Linux { + + public: + + //@{ + /// Basic Linux types. + typedef uint64_t size_t; + typedef uint64_t off_t; + typedef int64_t time_t; + typedef uint32_t uid_t; + typedef uint32_t gid_t; + //@} + +#if BSD_HOST + typedef struct stat hst_stat; + typedef struct stat hst_stat64; +#else + typedef struct stat hst_stat ; + typedef struct stat64 hst_stat64; +#endif + + + //@{ + /// open(2) flag values. + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + //@} + + /// This table maps the target open() flags to the corresponding + /// host open() flags. + static OpenFlagTransTable openFlagTable[]; + + /// Number of entries in openFlagTable[]. + static const int NUM_OPEN_FLAGS; + + /// Stat buffer. Note that we can't call it 'stat' since that + /// gets #defined to something else on some systems. + struct tgt_stat { + uint32_t st_dev; //!< device + uint32_t st_ino; //!< inode + uint32_t st_mode; //!< mode + uint32_t st_nlink; //!< link count + uint32_t st_uid; //!< owner's user ID + uint32_t st_gid; //!< owner's group ID + uint32_t st_rdev; //!< device number + int32_t _pad1; //!< for alignment + int64_t st_size; //!< file size in bytes + uint64_t st_atimeX; //!< time of last access + uint64_t st_mtimeX; //!< time of last modification + uint64_t st_ctimeX; //!< time of last status change + uint32_t st_blksize; //!< optimal I/O block size + int32_t st_blocks; //!< number of blocks allocated + uint32_t st_flags; //!< flags + uint32_t st_gen; //!< unknown + }; + + // same for stat64 + struct tgt_stat64 { + uint64_t st_dev; + uint64_t st_ino; + uint64_t st_rdev; + int64_t st_size; + uint64_t st_blocks; + + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + uint32_t st_blksize; + uint32_t st_nlink; + uint32_t __pad0; + + uint64_t tgt_st_atime; + uint64_t st_atime_nsec; + uint64_t tgt_st_mtime; + uint64_t st_mtime_nsec; + uint64_t tgt_st_ctime; + uint64_t st_ctime_nsec; + int64_t ___unused[3]; + }; + + /// Length of strings in struct utsname (plus 1 for null char). + static const int _SYS_NMLN = 65; + + /// Interface struct for uname(). + struct utsname { + char sysname[_SYS_NMLN]; //!< System name. + char nodename[_SYS_NMLN]; //!< Node name. + char release[_SYS_NMLN]; //!< OS release. + char version[_SYS_NMLN]; //!< OS version. + char machine[_SYS_NMLN]; //!< Machine type. + }; + + + //@{ + /// ioctl() command codes. + static const unsigned TIOCGETP = 0x40067408; + static const unsigned TIOCSETP = 0x80067409; + static const unsigned TIOCSETN = 0x8006740a; + static const unsigned TIOCSETC = 0x80067411; + static const unsigned TIOCGETC = 0x40067412; + static const unsigned FIONREAD = 0x4004667f; + static const unsigned TIOCISATTY = 0x2000745e; + static const unsigned TIOCGETS = 0x402c7413; + static const unsigned TIOCGETA = 0x40127417; + //@} + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NOFILE = 6, + TGT_RLIMIT_AS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; + + /// Limit struct for getrlimit/setrlimit. + struct rlimit { + uint64_t rlim_cur; //!< soft limit + uint64_t rlim_max; //!< hard limit + }; + + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x10; + + /// For gettimeofday(). + struct timeval { + int64_t tv_sec; //!< seconds + int64_t tv_usec; //!< microseconds + }; + + // For writev/readv + struct tgt_iovec { + uint64_t iov_base; // void * + uint64_t iov_len; + }; + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + static const int TGT_RUSAGE_BOTH = -2; + //@} + + /// For getrusage(). + struct rusage { + struct timeval ru_utime; //!< user time used + struct timeval ru_stime; //!< system time used + int64_t ru_maxrss; //!< max rss + int64_t ru_ixrss; //!< integral shared memory size + int64_t ru_idrss; //!< integral unshared data " + int64_t ru_isrss; //!< integral unshared stack " + int64_t ru_minflt; //!< page reclaims - total vmfaults + int64_t ru_majflt; //!< page faults + int64_t ru_nswap; //!< swaps + int64_t ru_inblock; //!< block input operations + int64_t ru_oublock; //!< block output operations + int64_t ru_msgsnd; //!< messages sent + int64_t ru_msgrcv; //!< messages received + int64_t ru_nsignals; //!< signals received + int64_t ru_nvcsw; //!< voluntary context switches + int64_t ru_nivcsw; //!< involuntary " + }; + + /// Helper function to convert a host stat buffer to a target stat + /// buffer. Also copies the target buffer out to the simulated + /// memory space. Used by stat(), fstat(), and lstat(). +#if !BSD_HOST + static void + copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host) + { + TypedBufferArg<Linux::tgt_stat> tgt(addr); + + tgt->st_dev = htog(host->st_dev); + tgt->st_ino = htog(host->st_ino); + tgt->st_mode = htog(host->st_mode); + tgt->st_nlink = htog(host->st_nlink); + tgt->st_uid = htog(host->st_uid); + tgt->st_gid = htog(host->st_gid); + tgt->st_rdev = htog(host->st_rdev); + tgt->st_size = htog(host->st_size); + tgt->st_atimeX = htog(host->st_atime); + tgt->st_mtimeX = htog(host->st_mtime); + tgt->st_ctimeX = htog(host->st_ctime); + tgt->st_blksize = htog(host->st_blksize); + tgt->st_blocks = htog(host->st_blocks); + + tgt.copyOut(mem); + } +#else + // Third version for bsd systems which no longer have any support for + // the old stat() call and stat() is actually a stat64() + static void + copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host) + { + TypedBufferArg<Linux::tgt_stat> tgt(addr); + + tgt->st_dev = htog(host->st_dev); + tgt->st_ino = htog(host->st_ino); + tgt->st_mode = htog(host->st_mode); + tgt->st_nlink = htog(host->st_nlink); + tgt->st_uid = htog(host->st_uid); + tgt->st_gid = htog(host->st_gid); + tgt->st_rdev = htog(host->st_rdev); + tgt->st_size = htog(host->st_size); + tgt->st_atimeX = htog(host->st_atime); + tgt->st_mtimeX = htog(host->st_mtime); + tgt->st_ctimeX = htog(host->st_ctime); + tgt->st_blksize = htog(host->st_blksize); + tgt->st_blocks = htog(host->st_blocks); + + tgt.copyOut(mem); + } +#endif + + + // Same for stat64 + static void + copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host) + { + TypedBufferArg<Linux::tgt_stat64> tgt(addr); + + // fd == 1 checks are because libc does some checks + // that the stdout is interactive vs. a file + // this makes it work on non-linux systems + if (fd == 1) + tgt->st_dev = htog((uint64_t)0xA); + else + tgt->st_dev = htog((uint64_t)host->st_dev); + // XXX What about STAT64_HAS_BROKEN_ST_INO ??? + tgt->st_ino = htog((uint64_t)host->st_ino); + if (fd == 1) + tgt->st_rdev = htog((uint64_t)0x880d); + else + tgt->st_rdev = htog((uint64_t)host->st_rdev); + tgt->st_size = htog((int64_t)host->st_size); + tgt->st_blocks = htog((uint64_t)host->st_blocks); + + if (fd == 1) + tgt->st_mode = htog((uint32_t)0x2190); + else + tgt->st_mode = htog((uint32_t)host->st_mode); + tgt->st_uid = htog((uint32_t)host->st_uid); + tgt->st_gid = htog((uint32_t)host->st_gid); + tgt->st_blksize = htog((uint32_t)host->st_blksize); + tgt->st_nlink = htog((uint32_t)host->st_nlink); + tgt->tgt_st_atime = htog((uint64_t)host->st_atime); + tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime); + tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime); +#if defined(STAT_HAVE_NSEC) + tgt->st_atime_nsec = htog(host->st_atime_nsec); + tgt->st_mtime_nsec = htog(host->st_mtime_nsec); + tgt->st_ctime_nsec = htog(host->st_ctime_nsec); +#else + tgt->st_atime_nsec = 0; + tgt->st_mtime_nsec = 0; + tgt->st_ctime_nsec = 0; +#endif + + tgt.copyOut(mem); + } + +}; // class Linux + + +#endif // FULL_SYSTEM + #endif // __LINUX_HH__ diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc index 26a4c0d3e..c5a9e184a 100644 --- a/kern/linux/linux_system.cc +++ b/kern/linux/linux_system.cc @@ -50,6 +50,7 @@ #include "targetarch/vtophys.hh" using namespace std; +using namespace TheISA; LinuxSystem::LinuxSystem(Params *p) : System(p) diff --git a/kern/linux/linux_threadinfo.hh b/kern/linux/linux_threadinfo.hh index 9bab1dc49..a1c378d6a 100644 --- a/kern/linux/linux_threadinfo.hh +++ b/kern/linux/linux_threadinfo.hh @@ -53,7 +53,7 @@ class ThreadInfo * thread_info struct. So we can get the address by masking off * the lower 14 bits. */ - current = xc->regs.intRegFile[StackPointerReg] & ~0x3fff; + current = xc->regs.intRegFile[TheISA::StackPointerReg] & ~0x3fff; return VPtr<thread_info>(xc, current); } diff --git a/kern/system_events.cc b/kern/system_events.cc index ba3c9274a..55595b9b6 100644 --- a/kern/system_events.cc +++ b/kern/system_events.cc @@ -29,6 +29,8 @@ #include "encumbered/cpu/full/cpu.hh" #include "kern/kernel_stats.hh" +using namespace TheISA; + void SkipFuncEvent::process(ExecContext *xc) { diff --git a/kern/tru64/dump_mbuf.cc b/kern/tru64/dump_mbuf.cc index 85cb4de96..efdaed62d 100644 --- a/kern/tru64/dump_mbuf.cc +++ b/kern/tru64/dump_mbuf.cc @@ -38,6 +38,8 @@ #include "arch/isa_traits.hh" #include "targetarch/vtophys.hh" +using namespace TheISA; + namespace tru64 { void diff --git a/kern/tru64/tru64.hh b/kern/tru64/tru64.hh index 07c0d21a7..1579a54d8 100644 --- a/kern/tru64/tru64.hh +++ b/kern/tru64/tru64.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2001-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,1297 @@ #ifndef __TRU64_HH__ #define __TRU64_HH__ +#include "config/full_system.hh" + +#if FULL_SYSTEM class Tru64 {}; +#else //!FULL_SYSTEM + +#include <sys/types.h> +#include <sys/stat.h> +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__) +#include <sys/param.h> +#include <sys/mount.h> +#else +#include <sys/statfs.h> +#endif + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> // for memset() +#include <unistd.h> + +#include "cpu/base.hh" +#include "sim/root.hh" +#include "sim/syscall_emul.hh" + +using namespace std; + +typedef struct stat global_stat; +typedef struct statfs global_statfs; +typedef struct dirent global_dirent; + +/// +/// This class encapsulates the types, structures, constants, +/// functions, and syscall-number mappings specific to the Alpha Tru64 +/// syscall interface. +/// +class Tru64 { + + public: + + //@{ + /// Basic Tru64 types. + typedef uint64_t size_t; + typedef uint64_t off_t; + typedef uint16_t nlink_t; + typedef int32_t dev_t; + typedef uint32_t uid_t; + typedef uint32_t gid_t; + typedef uint32_t time_t; + typedef uint32_t mode_t; + typedef uint32_t ino_t; + typedef struct { int val[2]; } quad; + typedef quad fsid_t; + //@} + + //@{ + /// open(2) flag values. + static const int TGT_O_RDONLY = 00000000; + static const int TGT_O_WRONLY = 00000001; + static const int TGT_O_RDWR = 00000002; + static const int TGT_O_NONBLOCK = 00000004; + static const int TGT_O_APPEND = 00000010; + static const int TGT_O_CREAT = 00001000; + static const int TGT_O_TRUNC = 00002000; + static const int TGT_O_EXCL = 00004000; + static const int TGT_O_NOCTTY = 00010000; + static const int TGT_O_SYNC = 00040000; + static const int TGT_O_DRD = 00100000; + static const int TGT_O_DIRECTIO = 00200000; + static const int TGT_O_CACHE = 00400000; + static const int TGT_O_DSYNC = 02000000; + static const int TGT_O_RSYNC = 04000000; + //@} + + /// This table maps the target open() flags to the corresponding + /// host open() flags. + static OpenFlagTransTable openFlagTable[]; + + /// Number of entries in openFlagTable[]. + static const int NUM_OPEN_FLAGS; + + /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat + /// structure, and a new set of syscall numbers for stat calls. + /// On some hosts (notably Linux) define st_atime, st_mtime, and + /// st_ctime as macros, so we append an X to get around this. + struct F64_stat { + dev_t st_dev; //!< st_dev + int32_t st_retired1; //!< st_retired1 + mode_t st_mode; //!< st_mode + nlink_t st_nlink; //!< st_nlink + uint16_t st_nlink_reserved; //!< st_nlink_reserved + uid_t st_uid; //!< st_uid + gid_t st_gid; //!< st_gid + dev_t st_rdev; //!< st_rdev + dev_t st_ldev; //!< st_ldev + off_t st_size; //!< st_size + time_t st_retired2; //!< st_retired2 + int32_t st_uatime; //!< st_uatime + time_t st_retired3; //!< st_retired3 + int32_t st_umtime; //!< st_umtime + time_t st_retired4; //!< st_retired4 + int32_t st_uctime; //!< st_uctime + int32_t st_retired5; //!< st_retired5 + int32_t st_retired6; //!< st_retired6 + uint32_t st_flags; //!< st_flags + uint32_t st_gen; //!< st_gen + uint64_t st_spare[4]; //!< st_spare[4] + ino_t st_ino; //!< st_ino + int32_t st_ino_reserved; //!< st_ino_reserved + time_t st_atimeX; //!< st_atime + int32_t st_atime_reserved; //!< st_atime_reserved + time_t st_mtimeX; //!< st_mtime + int32_t st_mtime_reserved; //!< st_mtime_reserved + time_t st_ctimeX; //!< st_ctime + int32_t st_ctime_reserved; //!< st_ctime_reserved + uint64_t st_blksize; //!< st_blksize + uint64_t st_blocks; //!< st_blocks + }; + + + /// Old Tru64 v4.x stat struct. + /// Tru64 maintains backwards compatibility with v4.x by + /// implementing another set of stat functions using the old + /// structure definition and binding them to the old syscall + /// numbers. + struct pre_F64_stat { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atimeX; + int32_t st_uatime; + time_t st_mtimeX; + int32_t st_umtime; + time_t st_ctimeX; + int32_t st_uctime; + uint32_t st_blksize; + int32_t st_blocks; + uint32_t st_flags; + uint32_t st_gen; + }; + + /// For statfs(). + struct F64_statfs { + int16_t f_type; + int16_t f_flags; + int32_t f_retired1; + int32_t f_retired2; + int32_t f_retired3; + int32_t f_retired4; + int32_t f_retired5; + int32_t f_retired6; + int32_t f_retired7; + fsid_t f_fsid; + int32_t f_spare[9]; + char f_retired8[90]; + char f_retired9[90]; + uint64_t dummy[10]; // was union mount_info mount_info; + uint64_t f_flags2; + int64_t f_spare2[14]; + int64_t f_fsize; + int64_t f_bsize; + int64_t f_blocks; + int64_t f_bfree; + int64_t f_bavail; + int64_t f_files; + int64_t f_ffree; + char f_mntonname[1024]; + char f_mntfromname[1024]; + }; + + /// For old Tru64 v4.x statfs() + struct pre_F64_statfs { + int16_t f_type; + int16_t f_flags; + int32_t f_fsize; + int32_t f_bsize; + int32_t f_blocks; + int32_t f_bfree; + int32_t f_bavail; + int32_t f_files; + int32_t f_ffree; + fsid_t f_fsid; + int32_t f_spare[9]; + char f_mntonname[90]; + char f_mntfromname[90]; + uint64_t dummy[10]; // was union mount_info mount_info; + }; + + /// For getdirentries(). + struct dirent + { + ino_t d_ino; //!< file number of entry + uint16_t d_reclen; //!< length of this record + uint16_t d_namlen; //!< length of string in d_name + char d_name[256]; //!< dummy name length + }; + + + /// Length of strings in struct utsname (plus 1 for null char). + static const int _SYS_NMLN = 32; + + /// Interface struct for uname(). + struct utsname { + char sysname[_SYS_NMLN]; //!< System name. + char nodename[_SYS_NMLN]; //!< Node name. + char release[_SYS_NMLN]; //!< OS release. + char version[_SYS_NMLN]; //!< OS version. + char machine[_SYS_NMLN]; //!< Machine type. + }; + + //@{ + /// ioctl() command codes. + static const unsigned TIOCGETP = 0x40067408; + static const unsigned TIOCSETP = 0x80067409; + static const unsigned TIOCSETN = 0x8006740a; + static const unsigned TIOCSETC = 0x80067411; + static const unsigned TIOCGETC = 0x40067412; + static const unsigned FIONREAD = 0x4004667f; + static const unsigned TIOCISATTY = 0x2000745e; + // TIOCGETS not defined in tru64, so I made up a number + static const unsigned TIOCGETS = 0x40000000; + static const unsigned TIOCGETA = 0x402c7413; + //@} + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NOFILE = 6, + TGT_RLIMIT_AS = 7, + TGT_RLIMIT_VMEM = 7 + }; + + /// Limit struct for getrlimit/setrlimit. + struct rlimit { + uint64_t rlim_cur; //!< soft limit + uint64_t rlim_max; //!< hard limit + }; + + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x10; + + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + //@} + + /// For getsysinfo() GSI_CPU_INFO option. + struct cpu_info { + uint32_t current_cpu; //!< current_cpu + uint32_t cpus_in_box; //!< cpus_in_box + uint32_t cpu_type; //!< cpu_type + uint32_t ncpus; //!< ncpus + uint64_t cpus_present; //!< cpus_present + uint64_t cpus_running; //!< cpus_running + uint64_t cpu_binding; //!< cpu_binding + uint64_t cpu_ex_binding; //!< cpu_ex_binding + uint32_t mhz; //!< mhz + uint32_t unused[3]; //!< future expansion + }; + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + /// For gettimeofday. + struct timeval { + uint32_t tv_sec; //!< seconds + uint32_t tv_usec; //!< microseconds + }; + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_THREAD = 1; + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + //@} + + /// For getrusage(). + struct rusage { + struct timeval ru_utime; //!< user time used + struct timeval ru_stime; //!< system time used + uint64_t ru_maxrss; //!< ru_maxrss + uint64_t ru_ixrss; //!< integral shared memory size + uint64_t ru_idrss; //!< integral unshared data " + uint64_t ru_isrss; //!< integral unshared stack " + uint64_t ru_minflt; //!< page reclaims - total vmfaults + uint64_t ru_majflt; //!< page faults + uint64_t ru_nswap; //!< swaps + uint64_t ru_inblock; //!< block input operations + uint64_t ru_oublock; //!< block output operations + uint64_t ru_msgsnd; //!< messages sent + uint64_t ru_msgrcv; //!< messages received + uint64_t ru_nsignals; //!< signals received + uint64_t ru_nvcsw; //!< voluntary context switches + uint64_t ru_nivcsw; //!< involuntary " + }; + + /// For sigreturn(). + struct sigcontext { + int64_t sc_onstack; //!< sigstack state to restore + int64_t sc_mask; //!< signal mask to restore + int64_t sc_pc; //!< pc at time of signal + int64_t sc_ps; //!< psl to retore + int64_t sc_regs[32]; //!< processor regs 0 to 31 + int64_t sc_ownedfp; //!< fp has been used + int64_t sc_fpregs[32]; //!< fp regs 0 to 31 + uint64_t sc_fpcr; //!< floating point control reg + uint64_t sc_fp_control; //!< software fpcr + int64_t sc_reserved1; //!< reserved for kernel + uint32_t sc_kreserved1; //!< reserved for kernel + uint32_t sc_kreserved2; //!< reserved for kernel + size_t sc_ssize; //!< stack size + caddr_t sc_sbase; //!< stack start + uint64_t sc_traparg_a0; //!< a0 argument to trap on exc + uint64_t sc_traparg_a1; //!< a1 argument to trap on exc + uint64_t sc_traparg_a2; //!< a2 argument to trap on exc + uint64_t sc_fp_trap_pc; //!< imprecise pc + uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg + uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc + }; + + + /// For table(). + static const int TBL_SYSINFO = 12; + + /// For table(). + struct tbl_sysinfo { + uint64_t si_user; //!< User time + uint64_t si_nice; //!< Nice time + uint64_t si_sys; //!< System time + uint64_t si_idle; //!< Idle time + uint64_t si_hz; //!< hz + uint64_t si_phz; //!< phz + uint64_t si_boottime; //!< Boot time in seconds + uint64_t wait; //!< Wait time + uint32_t si_max_procs; //!< rpb->rpb_numprocs + uint32_t pad; //!< padding + }; + + + /// For stack_create. + struct vm_stack { + // was void * + Addr address; //!< address hint + size_t rsize; //!< red zone size + size_t ysize; //!< yellow zone size + size_t gsize; //!< green zone size + size_t swap; //!< amount of swap to reserve + size_t incr; //!< growth increment + uint64_t align; //!< address alignment + uint64_t flags; //!< MAP_FIXED etc. + // was struct memalloc_attr * + Addr attr; //!< allocation policy + uint64_t reserved; //!< reserved + }; + + /// Return values for nxm calls. + enum { + KERN_NOT_RECEIVER = 7, + KERN_NOT_IN_SET = 12 + }; + + /// For nxm_task_init. + static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP + + /// Task attribute structure. + struct nxm_task_attr { + int64_t nxm_callback; //!< nxm_callback + unsigned int nxm_version; //!< nxm_version + unsigned short nxm_uniq_offset; //!< nxm_uniq_offset + unsigned short flags; //!< flags + int nxm_quantum; //!< nxm_quantum + int pad1; //!< pad1 + int64_t pad2; //!< pad2 + }; + + /// Signal set. + typedef uint64_t sigset_t; + + /// Thread state shared between user & kernel. + struct ushared_state { + sigset_t sigmask; //!< thread signal mask + sigset_t sig; //!< thread pending mask + // struct nxm_pth_state * + Addr pth_id; //!< out-of-line state + int flags; //!< shared flags +#define US_SIGSTACK 0x1 // thread called sigaltstack +#define US_ONSTACK 0x2 // thread is running on altstack +#define US_PROFILE 0x4 // thread called profil +#define US_SYSCALL 0x8 // thread in syscall +#define US_TRAP 0x10 // thread has trapped +#define US_YELLOW 0x20 // thread has mellowed yellow +#define US_YZONE 0x40 // thread has zoned out +#define US_FP_OWNED 0x80 // thread used floating point + + int cancel_state; //!< thread's cancelation state +#define US_CANCEL 0x1 // cancel pending +#define US_NOCANCEL 0X2 // synch cancel disabled +#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled +#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled +#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL) +#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \ + US_ASYNC_NOCANCEL) + + // These are semi-shared. They are always visible to + // the kernel but are never context-switched by the library. + + int nxm_ssig; //!< scheduler's synchronous signals + int reserved1; //!< reserved1 + int64_t nxm_active; //!< scheduler active + int64_t reserved2; //!< reserved2 + }; + + struct nxm_sched_state { + struct ushared_state nxm_u; //!< state own by user thread + unsigned int nxm_bits; //!< scheduler state / slot + int nxm_quantum; //!< quantum count-down value + int nxm_set_quantum; //!< quantum reset value + int nxm_sysevent; //!< syscall state + // struct nxm_upcall * + Addr nxm_uc_ret; //!< stack ptr of null thread + // void * + Addr nxm_tid; //!< scheduler's thread id + int64_t nxm_va; //!< page fault address + // struct nxm_pth_state * + Addr nxm_pthid; //!< id of null thread + uint64_t nxm_bound_pcs_count; //!< bound PCS thread count + int64_t pad[2]; //!< pad + }; + + /// nxm_shared. + struct nxm_shared { + int64_t nxm_callback; //!< address of upcall routine + unsigned int nxm_version; //!< version number + unsigned short nxm_uniq_offset; //!< correction factor for TEB + unsigned short pad1; //!< pad1 + int64_t space[2]; //!< future growth + struct nxm_sched_state nxm_ss[1]; //!< array of shared areas + }; + + /// nxm_slot_state_t. + enum nxm_slot_state_t { + NXM_SLOT_AVAIL, + NXM_SLOT_BOUND, + NXM_SLOT_UNBOUND, + NXM_SLOT_EMPTY + }; + + /// nxm_config_info + struct nxm_config_info { + int nxm_nslots_per_rad; //!< max number of VP slots per RAD + int nxm_nrads; //!< max number of RADs + // nxm_slot_state_t * + Addr nxm_slot_state; //!< per-VP slot state + // struct nxm_shared * + Addr nxm_rad[1]; //!< per-RAD shared areas + }; + + /// For nxm_thread_create. + enum nxm_thread_type { + NXM_TYPE_SCS = 0, + NXM_TYPE_VP = 1, + NXM_TYPE_MANAGER = 2 + }; + + /// Thread attributes. + struct nxm_thread_attr { + int version; //!< version + int type; //!< type + int cancel_flags; //!< cancel_flags + int priority; //!< priority + int policy; //!< policy + int signal_type; //!< signal_type + // void * + Addr pthid; //!< pthid + sigset_t sigmask; //!< sigmask + /// Initial register values. + struct { + uint64_t pc; //!< pc + uint64_t sp; //!< sp + uint64_t a0; //!< a0 + } registers; + uint64_t pad2[2]; //!< pad2 + }; + + /// Helper function to convert a host stat buffer to a target stat + /// buffer. Also copies the target buffer out to the simulated + /// memory space. Used by stat(), fstat(), and lstat(). + template <class T> + static void + copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host) + { + TypedBufferArg<T> tgt(addr); + + tgt->st_dev = htog(host->st_dev); + tgt->st_ino = htog(host->st_ino); + tgt->st_mode = htog(host->st_mode); + tgt->st_nlink = htog(host->st_nlink); + tgt->st_uid = htog(host->st_uid); + tgt->st_gid = htog(host->st_gid); + tgt->st_rdev = htog(host->st_rdev); + tgt->st_size = htog(host->st_size); + tgt->st_atimeX = htog(host->st_atime); + tgt->st_mtimeX = htog(host->st_mtime); + tgt->st_ctimeX = htog(host->st_ctime); + tgt->st_blksize = htog(host->st_blksize); + tgt->st_blocks = htog(host->st_blocks); + + tgt.copyOut(mem); + } + + /// Helper function to convert a host statfs buffer to a target statfs + /// buffer. Also copies the target buffer out to the simulated + /// memory space. Used by statfs() and fstatfs(). + template <class T> + static void + copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host) + { + TypedBufferArg<T> tgt(addr); + +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__) + tgt->f_type = 0; +#else + tgt->f_type = htog(host->f_type); +#endif + tgt->f_bsize = htog(host->f_bsize); + tgt->f_blocks = htog(host->f_blocks); + tgt->f_bfree = htog(host->f_bfree); + tgt->f_bavail = htog(host->f_bavail); + tgt->f_files = htog(host->f_files); + tgt->f_ffree = htog(host->f_ffree); + + // Is this as string normally? + memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid)); + + tgt.copyOut(mem); + } + + class F64 { + public: + static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, + global_stat *host) + { + Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host); + } + + static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, + global_statfs *host) + { + Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host); + } + }; + + class PreF64 { + public: + static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, + global_stat *host) + { + Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host); + } + + static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, + global_statfs *host) + { + Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host); + } + }; + + /// Helper function to convert a host stat buffer to an old pre-F64 + /// (4.x) target stat buffer. Also copies the target buffer out to + /// the simulated memory space. Used by pre_F64_stat(), + /// pre_F64_fstat(), and pre_F64_lstat(). + static void + copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host) + { + TypedBufferArg<Tru64::pre_F64_stat> tgt(addr); + + tgt->st_dev = htog(host->st_dev); + tgt->st_ino = htog(host->st_ino); + tgt->st_mode = htog(host->st_mode); + tgt->st_nlink = htog(host->st_nlink); + tgt->st_uid = htog(host->st_uid); + tgt->st_gid = htog(host->st_gid); + tgt->st_rdev = htog(host->st_rdev); + tgt->st_size = htog(host->st_size); + tgt->st_atimeX = htog(host->st_atime); + tgt->st_mtimeX = htog(host->st_mtime); + tgt->st_ctimeX = htog(host->st_ctime); + tgt->st_blksize = htog(host->st_blksize); + tgt->st_blocks = htog(host->st_blocks); + + tgt.copyOut(mem); + } + + + /// The target system's hostname. + static const char *hostname; + + + /// Target getdirentries() handler. + static SyscallReturn + getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { +#ifdef __CYGWIN__ + panic("getdirent not implemented on cygwin!"); +#else + int fd = process->sim_fd(xc->getSyscallArg(0)); + Addr tgt_buf = xc->getSyscallArg(1); + int tgt_nbytes = xc->getSyscallArg(2); + Addr tgt_basep = xc->getSyscallArg(3); + + char * const host_buf = new char[tgt_nbytes]; + + // just pass basep through uninterpreted. + TypedBufferArg<int64_t> basep(tgt_basep); + basep.copyIn(xc->mem); + long host_basep = (off_t)htog((int64_t)*basep); + int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep); + + // check for error + if (host_result < 0) { + delete [] host_buf; + return -errno; + } + + // no error: copy results back to target space + Addr tgt_buf_ptr = tgt_buf; + char *host_buf_ptr = host_buf; + char *host_buf_end = host_buf + host_result; + while (host_buf_ptr < host_buf_end) { + global_dirent *host_dp = (global_dirent *)host_buf_ptr; + int namelen = strlen(host_dp->d_name); + + // Actual size includes padded string rounded up for alignment. + // Subtract 256 for dummy char array in Tru64::dirent definition. + // Add 1 to namelen for terminating null char. + int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8); + TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize); + tgt_dp->d_ino = host_dp->d_ino; + tgt_dp->d_reclen = tgt_bufsize; + tgt_dp->d_namlen = namelen; + strcpy(tgt_dp->d_name, host_dp->d_name); + tgt_dp.copyOut(xc->mem); + + tgt_buf_ptr += tgt_bufsize; + host_buf_ptr += host_dp->d_reclen; + } + + delete [] host_buf; + + *basep = htog((int64_t)host_basep); + basep.copyOut(xc->mem); + + return tgt_buf_ptr - tgt_buf; +#endif + } + + /// Target sigreturn() handler. + static SyscallReturn + sigreturnFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + using TheISA::RegFile; + RegFile *regs = &xc->regs; + TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0)); + + sc.copyIn(xc->mem); + + // Restore state from sigcontext structure. + // Note that we'll advance PC <- NPC before the end of the cycle, + // so we need to restore the desired PC into NPC. + // The current regs->pc will get clobbered. + regs->npc = htog(sc->sc_pc); + + for (int i = 0; i < 31; ++i) { + regs->intRegFile[i] = htog(sc->sc_regs[i]); + regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]); + } + + regs->miscRegs.fpcr = htog(sc->sc_fpcr); + + return 0; + } + + /// Target table() handler. + static SyscallReturn + tableFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + int id = xc->getSyscallArg(0); // table ID + int index = xc->getSyscallArg(1); // index into table + // arg 2 is buffer pointer; type depends on table ID + int nel = xc->getSyscallArg(3); // number of elements + int lel = xc->getSyscallArg(4); // expected element size + + switch (id) { + case Tru64::TBL_SYSINFO: { + if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) + return -EINVAL; + TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2)); + + const int clk_hz = one_million; + elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); + elp->si_nice = htog(0); + elp->si_sys = htog(0); + elp->si_idle = htog(0); + elp->wait = htog(0); + elp->si_hz = htog(clk_hz); + elp->si_phz = htog(clk_hz); + elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? + elp->si_max_procs = htog(process->numCpus()); + elp.copyOut(xc->mem); + return 0; + } + + default: + cerr << "table(): id " << id << " unknown." << endl; + return -EINVAL; + } + } + + // + // Mach syscalls -- identified by negated syscall numbers + // + + /// Create a stack region for a thread. + static SyscallReturn + stack_createFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0)); + + argp.copyIn(xc->mem); + + // if the user chose an address, just let them have it. Otherwise + // pick one for them. + if (htog(argp->address) == 0) { + argp->address = htog(process->next_thread_stack_base); + int stack_size = (htog(argp->rsize) + htog(argp->ysize) + + htog(argp->gsize)); + process->next_thread_stack_base -= stack_size; + argp.copyOut(xc->mem); + } + + return 0; + } + + /// NXM library version stamp. + static + const int NXM_LIB_VERSION = 301003; + + /// This call sets up the interface between the user and kernel + /// schedulers by creating a shared-memory region. The shared memory + /// region has several structs, some global, some per-RAD, some per-VP. + static SyscallReturn + nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0)); + TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1)); + + attrp.copyIn(xc->mem); + + if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) { + cerr << "nxm_task_init: thread library version mismatch! " + << "got " << attrp->nxm_version + << ", expected " << NXM_LIB_VERSION << endl; + abort(); + } + + if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) { + cerr << "nxm_task_init: bad flag value " << attrp->flags + << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl; + abort(); + } + + const Addr base_addr = 0x12000; // was 0x3f0000000LL; + Addr cur_addr = base_addr; // next addresses to use + // first comes the config_info struct + Addr config_addr = cur_addr; + cur_addr += sizeof(Tru64::nxm_config_info); + // next comes the per-cpu state vector + Addr slot_state_addr = cur_addr; + int slot_state_size = + process->numCpus() * sizeof(Tru64::nxm_slot_state_t); + cur_addr += slot_state_size; + // now the per-RAD state struct (we only support one RAD) + cur_addr = 0x14000; // bump up addr for alignment + Addr rad_state_addr = cur_addr; + int rad_state_size = + (sizeof(Tru64::nxm_shared) + + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state)); + cur_addr += rad_state_size; + + // now initialize a config_info struct and copy it out to user space + TypedBufferArg<Tru64::nxm_config_info> config(config_addr); + + config->nxm_nslots_per_rad = htog(process->numCpus()); + config->nxm_nrads = htog(1); // only one RAD in our system! + config->nxm_slot_state = htog(slot_state_addr); + config->nxm_rad[0] = htog(rad_state_addr); + + config.copyOut(xc->mem); + + // initialize the slot_state array and copy it out + TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr, + slot_state_size); + for (int i = 0; i < process->numCpus(); ++i) { + // CPU 0 is bound to the calling process; all others are available + // XXX this code should have an endian conversion, but I don't think + // it works anyway + slot_state[i] = + (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL; + } + + slot_state.copyOut(xc->mem); + + // same for the per-RAD "shared" struct. Note that we need to + // allocate extra bytes for the per-VP array which is embedded at + // the end. + TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr, + rad_state_size); + + rad_state->nxm_callback = attrp->nxm_callback; + rad_state->nxm_version = attrp->nxm_version; + rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset; + for (int i = 0; i < process->numCpus(); ++i) { + Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i]; + ssp->nxm_u.sigmask = htog(0); + ssp->nxm_u.sig = htog(0); + ssp->nxm_u.flags = htog(0); + ssp->nxm_u.cancel_state = htog(0); + ssp->nxm_u.nxm_ssig = 0; + ssp->nxm_bits = htog(0); + ssp->nxm_quantum = attrp->nxm_quantum; + ssp->nxm_set_quantum = attrp->nxm_quantum; + ssp->nxm_sysevent = htog(0); + + if (i == 0) { + uint64_t uniq = xc->regs.miscRegs.uniq; + ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset)); + ssp->nxm_u.nxm_active = htog(uniq | 1); + } + else { + ssp->nxm_u.pth_id = htog(0); + ssp->nxm_u.nxm_active = htog(0); + } + } + + rad_state.copyOut(xc->mem); + + // + // copy pointer to shared config area out to user + // + *configptr_ptr = htog(config_addr); + configptr_ptr.copyOut(xc->mem); + + // Register this as a valid address range with the process + process->nxm_start = base_addr; + process->nxm_end = cur_addr; + + return 0; + } + + /// Initialize execution context. + static void + init_exec_context(ExecContext *ec, + Tru64::nxm_thread_attr *attrp, uint64_t uniq_val) + { + memset(&ec->regs, 0, sizeof(ec->regs)); + + ec->regs.intRegFile[TheISA::ArgumentReg0] = gtoh(attrp->registers.a0); + ec->regs.intRegFile[27/*t12*/] = gtoh(attrp->registers.pc); + ec->regs.intRegFile[TheISA::StackPointerReg] = gtoh(attrp->registers.sp); + ec->regs.miscRegs.uniq = uniq_val; + + ec->regs.pc = gtoh(attrp->registers.pc); + ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst); + + ec->activate(); + } + + /// Create thread. + static SyscallReturn + nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0)); + TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1)); + int thread_index = xc->getSyscallArg(2); + + // get attribute args + attrp.copyIn(xc->mem); + + if (gtoh(attrp->version) != NXM_LIB_VERSION) { + cerr << "nxm_thread_create: thread library version mismatch! " + << "got " << attrp->version + << ", expected " << NXM_LIB_VERSION << endl; + abort(); + } + + if (thread_index < 0 | thread_index > process->numCpus()) { + cerr << "nxm_thread_create: bad thread index " << thread_index + << endl; + abort(); + } + + // On a real machine, the per-RAD shared structure is in + // shared memory, so both the user and kernel can get at it. + // We don't have that luxury, so we just copy it in and then + // back out again. + int rad_state_size = + (sizeof(Tru64::nxm_shared) + + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state)); + + TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000, + rad_state_size); + rad_state.copyIn(xc->mem); + + uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset); + + if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) { + // DEC pthreads seems to always create one of these (in + // addition to N application threads), but we don't use it, + // so don't bother creating it. + + // This is supposed to be a port number. Make something up. + *kidp = htog(99); + kidp.copyOut(xc->mem); + + return 0; + } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) { + // A real "virtual processor" kernel thread. Need to fork + // this thread on another CPU. + Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index]; + + if (gtoh(ssp->nxm_u.nxm_active) != 0) + return (int) Tru64::KERN_NOT_RECEIVER; + + ssp->nxm_u.pth_id = attrp->pthid; + ssp->nxm_u.nxm_active = htog(uniq_val | 1); + + rad_state.copyOut(xc->mem); + + Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info); + int slot_state_size = + process->numCpus() * sizeof(Tru64::nxm_slot_state_t); + + TypedBufferArg<Tru64::nxm_slot_state_t> + slot_state(slot_state_addr, + slot_state_size); + + slot_state.copyIn(xc->mem); + + if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) { + cerr << "nxm_thread_createFunc: requested VP slot " + << thread_index << " not available!" << endl; + fatal(""); + } + + // XXX This should have an endian conversion but I think this code + // doesn't work anyway + slot_state[thread_index] = Tru64::NXM_SLOT_BOUND; + + slot_state.copyOut(xc->mem); + + // Find a free simulator execution context. + for (int i = 0; i < process->numCpus(); ++i) { + ExecContext *xc = process->execContexts[i]; + + if (xc->status() == ExecContext::Unallocated) { + // inactive context... grab it + init_exec_context(xc, attrp, uniq_val); + + // This is supposed to be a port number, but we'll try + // and get away with just sticking the thread index + // here. + *kidp = htog(thread_index); + kidp.copyOut(xc->mem); + + return 0; + } + } + + // fell out of loop... no available inactive context + cerr << "nxm_thread_create: no idle contexts available." << endl; + abort(); + } else { + cerr << "nxm_thread_create: can't handle thread type " + << attrp->type << endl; + abort(); + } + + return 0; + } + + /// Thread idle call (like yield()). + static SyscallReturn + nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + return 0; + } + + /// Block thread. + static SyscallReturn + nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + uint64_t tid = xc->getSyscallArg(0); + uint64_t secs = xc->getSyscallArg(1); + uint64_t flags = xc->getSyscallArg(2); + uint64_t action = xc->getSyscallArg(3); + uint64_t usecs = xc->getSyscallArg(4); + + cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs + << " " << flags << " " << action << " " << usecs << endl; + + return 0; + } + + /// block. + static SyscallReturn + nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr uaddr = xc->getSyscallArg(0); + uint64_t val = xc->getSyscallArg(1); + uint64_t secs = xc->getSyscallArg(2); + uint64_t usecs = xc->getSyscallArg(3); + uint64_t flags = xc->getSyscallArg(4); + + BaseCPU *cpu = xc->cpu; + + cout << cpu->name() << ": nxm_block " + << hex << uaddr << dec << " " << val + << " " << secs << " " << usecs + << " " << flags << endl; + + return 0; + } + + /// Unblock thread. + static SyscallReturn + nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr uaddr = xc->getSyscallArg(0); + + cout << xc->cpu->name() << ": nxm_unblock " + << hex << uaddr << dec << endl; + + return 0; + } + + /// Switch thread priority. + static SyscallReturn + swtch_priFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + // Attempts to switch to another runnable thread (if there is + // one). Returns false if there are no other threads to run + // (i.e., the thread can reasonably spin-wait) or true if there + // are other threads. + // + // Since we assume at most one "kernel" thread per CPU, it's + // always safe to return false here. + return 0; //false; + } + + + /// Activate exec context waiting on a channel. Just activate one + /// by default. + static int + activate_waiting_context(Addr uaddr, Process *process, + bool activate_all = false) + { + int num_activated = 0; + + list<Process::WaitRec>::iterator i = process->waitList.begin(); + list<Process::WaitRec>::iterator end = process->waitList.end(); + + while (i != end && (num_activated == 0 || activate_all)) { + if (i->waitChan == uaddr) { + // found waiting process: make it active + ExecContext *newCtx = i->waitingContext; + assert(newCtx->status() == ExecContext::Suspended); + newCtx->activate(); + + // get rid of this record + i = process->waitList.erase(i); + + ++num_activated; + } else { + ++i; + } + } + + return num_activated; + } + + /// M5 hacked-up lock acquire. + static void + m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc) + { + TypedBufferArg<uint64_t> lockp(uaddr); + + lockp.copyIn(xc->mem); + + if (gtoh(*lockp) == 0) { + // lock is free: grab it + *lockp = htog(1); + lockp.copyOut(xc->mem); + } else { + // lock is busy: disable until free + process->waitList.push_back(Process::WaitRec(uaddr, xc)); + xc->suspend(); + } + } + + /// M5 unlock call. + static void + m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc) + { + TypedBufferArg<uint64_t> lockp(uaddr); + + lockp.copyIn(xc->mem); + assert(*lockp != 0); + + // Check for a process waiting on the lock. + int num_waiting = activate_waiting_context(uaddr, process); + + // clear lock field if no waiting context is taking over the lock + if (num_waiting == 0) { + *lockp = 0; + lockp.copyOut(xc->mem); + } + } + + /// Lock acquire syscall handler. + static SyscallReturn + m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr uaddr = xc->getSyscallArg(0); + + m5_lock_mutex(uaddr, process, xc); + + // Return 0 since we will always return to the user with the lock + // acquired. We will just keep the context inactive until that is + // true. + return 0; + } + + /// Try lock (non-blocking). + static SyscallReturn + m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr uaddr = xc->getSyscallArg(0); + TypedBufferArg<uint64_t> lockp(uaddr); + + lockp.copyIn(xc->mem); + + if (gtoh(*lockp) == 0) { + // lock is free: grab it + *lockp = htog(1); + lockp.copyOut(xc->mem); + return 0; + } else { + return 1; + } + } + + /// Unlock syscall handler. + static SyscallReturn + m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr uaddr = xc->getSyscallArg(0); + + m5_unlock_mutex(uaddr, process, xc); + + return 0; + } + + /// Signal ocndition. + static SyscallReturn + m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr cond_addr = xc->getSyscallArg(0); + + // Wake up one process waiting on the condition variable. + activate_waiting_context(cond_addr, process); + + return 0; + } + + /// Wake up all processes waiting on the condition variable. + static SyscallReturn + m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr cond_addr = xc->getSyscallArg(0); + + activate_waiting_context(cond_addr, process, true); + + return 0; + } + + /// Wait on a condition. + static SyscallReturn + m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + Addr cond_addr = xc->getSyscallArg(0); + Addr lock_addr = xc->getSyscallArg(1); + TypedBufferArg<uint64_t> condp(cond_addr); + TypedBufferArg<uint64_t> lockp(lock_addr); + + // user is supposed to acquire lock before entering + lockp.copyIn(xc->mem); + assert(gtoh(*lockp) != 0); + + m5_unlock_mutex(lock_addr, process, xc); + + process->waitList.push_back(Process::WaitRec(cond_addr, xc)); + xc->suspend(); + + return 0; + } + + /// Thread exit. + static SyscallReturn + m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + assert(xc->status() == ExecContext::Active); + xc->deallocate(); + + return 0; + } + + /// Indirect syscall invocation (call #0). + static SyscallReturn + indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) + { + int new_callnum = xc->getSyscallArg(0); + LiveProcess *lp = dynamic_cast<LiveProcess*>(process); + assert(lp); + + for (int i = 0; i < 5; ++i) + xc->setSyscallArg(i, xc->getSyscallArg(i+1)); + + + SyscallDesc *new_desc = lp->getDesc(new_callnum); + if (desc == NULL) + fatal("Syscall %d out of range", callnum); + + new_desc->doSyscall(new_callnum, process, xc); + + return 0; + } + +}; // class Tru64 + + +#endif // FULL_SYSTEM + #endif // __TRU64_HH__ diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc index d769aab0f..2fe6a2dc4 100644 --- a/kern/tru64/tru64_events.cc +++ b/kern/tru64/tru64_events.cc @@ -36,6 +36,8 @@ #include "targetarch/arguments.hh" #include "arch/isa_traits.hh" +using namespace TheISA; + //void SkipFuncEvent::process(ExecContext *xc); void diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py index f58ece0be..3a7f88d04 100644 --- a/python/m5/objects/Ethernet.py +++ b/python/m5/objects/Ethernet.py @@ -76,7 +76,6 @@ class EtherDevBase(PciDevice): dma_write_delay = Param.Latency('0us', "fixed delay for dma writes") dma_write_factor = Param.Latency('0us', "multiplier for dma writes") dma_no_allocate = Param.Bool(True, "Should we allocate cache on read") - pio_delay_write = Param.Bool(False, "Delay pio writes until timing occurs") rx_delay = Param.Latency('1us', "Receive Delay") tx_delay = Param.Latency('1us', "Transmit Delay") diff --git a/sim/faults.cc b/sim/faults.cc new file mode 100644 index 000000000..58a631263 --- /dev/null +++ b/sim/faults.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sim/faults.hh" + +NoFaultType * const NoFault = new NoFaultType("none"); +MachineCheckFaultType * const MachineCheckFault = + new MachineCheckFaultType("mchk"); +AlignmentFaultType * const AlignmentFault = + new AlignmentFaultType("unalign"); + diff --git a/sim/faults.hh b/sim/faults.hh new file mode 100644 index 000000000..dbec399af --- /dev/null +++ b/sim/faults.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FAULTS_HH__ +#define __FAULTS_HH__ + +class FaultBase; +typedef FaultBase * Fault; + +class FaultBase +{ +public: + FaultBase(char * newName, int newId = 0) : name(newName), id(newId) {;} + const char * name; + int id; +}; + +extern class NoFaultType : public FaultBase +{ +public: + NoFaultType(char * newName) : FaultBase(newName) {;} +} * const NoFault; + +extern class MachineCheckFaultType : public FaultBase +{ +public: + MachineCheckFaultType(char * newName) : FaultBase(newName) {;} +} * const MachineCheckFault; + +extern class AlignmentFaultType : public FaultBase +{ +public: + AlignmentFaultType(char * newName) : FaultBase(newName) {;} +} * const AlignmentFault; + + +#endif // __FAULTS_HH__ diff --git a/sim/host.hh b/sim/host.hh index ef7008042..f7e64f23c 100644 --- a/sim/host.hh +++ b/sim/host.hh @@ -54,4 +54,12 @@ typedef int64_t Counter; */ typedef int64_t Tick; +/** + * Address type + * This will probably be moved somewhere else in the near future. + * This should be at least as big as the biggest address width in use + * in the system, which will probably be 64 bits. + */ +typedef uint64_t Addr; + #endif // __HOST_H__ diff --git a/sim/process.cc b/sim/process.cc index 59d122b48..0a7e46082 100644 --- a/sim/process.cc +++ b/sim/process.cc @@ -46,6 +46,7 @@ #include "sim/fake_syscall.hh" #include "sim/process.hh" #include "sim/stats.hh" +#include "sim/syscall_emul.hh" #ifdef TARGET_ALPHA #include "arch/alpha/alpha_tru64_process.hh" @@ -53,6 +54,7 @@ #endif using namespace std; +using namespace TheISA; // // The purpose of this code is to fake the loader & syscall mechanism @@ -350,6 +352,19 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile, init_regs->npc = prog_entry + sizeof(MachInst); } +void +LiveProcess::syscall(ExecContext *xc) +{ + num_syscalls++; + + int64_t callnum = xc->regs.intRegFile[ReturnValueReg]; + + SyscallDesc *desc = getDesc(callnum); + if (desc == NULL) + fatal("Syscall %d out of range", callnum); + + desc->doSyscall(callnum, this, xc); +} LiveProcess * LiveProcess::create(const string &nm, @@ -394,6 +409,7 @@ LiveProcess::create(const string &nm, } + BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) VectorParam<string> cmd; diff --git a/sim/process.hh b/sim/process.hh index 43fafd9d7..71b7d02b3 100644 --- a/sim/process.hh +++ b/sim/process.hh @@ -48,8 +48,12 @@ class ExecContext; class FunctionalMemory; +class SyscallDesc; class Process : public SimObject { + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; public: // have we initialized an execution context from this process? If @@ -200,6 +204,11 @@ class LiveProcess : public Process std::string executable, std::vector<std::string> &argv, std::vector<std::string> &envp); + + virtual void syscall(ExecContext *xc); + + virtual SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); } + }; diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc index 11ab55f53..58ea8266f 100644 --- a/sim/pseudo_inst.cc +++ b/sim/pseudo_inst.cc @@ -53,6 +53,7 @@ using namespace std; extern Sampler *SampCPU; using namespace Stats; +using namespace TheISA; namespace AlphaPseudo { diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc index 4b6388a41..d22dde3b8 100644 --- a/sim/syscall_emul.cc +++ b/sim/syscall_emul.cc @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <fcntl.h> #include <unistd.h> #include <string> @@ -40,6 +41,7 @@ #include "sim/sim_events.hh" using namespace std; +using namespace TheISA; void SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc) @@ -89,7 +91,7 @@ exitFunc(SyscallDesc *desc, int callnum, Process *process, SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { - return VMPageSize; + return (int)VMPageSize; } @@ -191,7 +193,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return (TheISA::IntReg)-EFAULT; int result = unlink(path.c_str()); @@ -203,12 +205,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string old_name; - if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != NoFault) return -EFAULT; string new_name; - if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault) + if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != NoFault) return -EFAULT; int64_t result = rename(old_name.c_str(), new_name.c_str()); @@ -220,7 +222,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; off_t length = xc->getSyscallArg(1); @@ -248,7 +250,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; /* XXX endianess */ @@ -278,3 +280,48 @@ fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) int result = fchown(fd, hostOwner, hostGroup); return (result == -1) ? -errno : result; } + + +SyscallReturn +fcntlFunc(SyscallDesc *desc, int num, Process *process, + ExecContext *xc) +{ + int fd = xc->getSyscallArg(0); + + if (fd < 0 || process->sim_fd(fd) < 0) + return -EBADF; + + int cmd = xc->getSyscallArg(1); + switch (cmd) { + case 0: // F_DUPFD + // if we really wanted to support this, we'd need to do it + // in the target fd space. + warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); + return -EMFILE; + + case 1: // F_GETFD (get close-on-exec flag) + case 2: // F_SETFD (set close-on-exec flag) + return 0; + + case 3: // F_GETFL (get file flags) + case 4: // F_SETFL (set file flags) + // not sure if this is totally valid, but we'll pass it through + // to the underlying OS + warn("fcntl(%d, %d) passed through to host\n", fd, cmd); + return fcntl(process->sim_fd(fd), cmd); + // return 0; + + case 7: // F_GETLK (get lock) + case 8: // F_SETLK (set lock) + case 9: // F_SETLKW (set lock and wait) + // don't mess with file locking... just act like it's OK + warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); + return 0; + + default: + warn("Unknown fcntl command %d\n", cmd); + return 0; + } +} + + diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh index d8029ddb0..f49248dea 100644 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@ -239,6 +239,10 @@ SyscallReturn chownFunc(SyscallDesc *desc, int num, SyscallReturn fchownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +/// Target fnctl() handler. +SyscallReturn fcntlFunc(SyscallDesc *desc, int num, + Process *process, ExecContext *xc); + /// This struct is used to build an target-OS-dependent table that /// maps the target's open() flags to the host open() flags. struct OpenFlagTransTable { @@ -317,7 +321,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; if (path == "/dev/sysdev0") { @@ -364,7 +368,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; uint32_t mode = xc->getSyscallArg(1); @@ -417,7 +421,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; struct stat hostBuf; @@ -469,7 +473,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; struct stat hostBuf; @@ -491,7 +495,7 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; #if BSD_HOST @@ -542,7 +546,7 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; struct statfs hostBuf; @@ -646,7 +650,7 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) if (start == 0) { // user didn't give an address... pick one from our "mmap region" start = p->mmap_end; - p->mmap_end += roundUp(length, VMPageSize); + p->mmap_end += roundUp(length, TheISA::VMPageSize); if (p->nxm_start != 0) { //If we have an nxm space, make sure we haven't colided assert(p->mmap_end < p->nxm_start); @@ -716,7 +720,7 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1)); diff --git a/sim/system.cc b/sim/system.cc index bf639b408..41de8cee4 100644 --- a/sim/system.cc +++ b/sim/system.cc @@ -41,6 +41,7 @@ #include "base/trace.hh" using namespace std; +using namespace TheISA; vector<System *> System::systemList; diff --git a/util/pbs/jobfile.py b/util/pbs/jobfile.py index d36b5ee6d..fd19b3bf5 100644 --- a/util/pbs/jobfile.py +++ b/util/pbs/jobfile.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005 The Regents of The University of Michigan +# Copyright (c) 2005-2006 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -277,10 +277,11 @@ class Option(Data): return name if attr == 'desc': - desc = self.__dict__[attr] - if self._suboption is not None: - desc = '%s, %s' % (desc, self._suboption.desc) - return desc + desc = [ self.__dict__[attr] ] + if self._suboption is not None and self._suboption.desc: + desc.append(self._suboption.desc) + return ', '.join(desc) + return super(Option, self).__getattribute__(attr) @@ -356,6 +357,8 @@ class Configuration(Data): def __init__(self, name, desc, **kwargs): super(Configuration, self).__init__(name, desc, **kwargs) self._groups = [] + self._posfilters = [] + self._negfilters = [] def group(self, name, desc, **kwargs): grp = Group(name, desc, **kwargs) @@ -402,13 +405,39 @@ class Configuration(Data): if checkpoint: yield options + def addfilter(self, filt, pos=True): + import re + filt = re.compile(filt) + if pos: + self._posfilters.append(filt) + else: + self._negfilters.append(filt) + + def jobfilter(self, job): + for filt in self._negfilters: + if filt.match(job.name): + return False + + if not self._posfilters: + return True + + for filt in self._posfilters: + if filt.match(job.name): + return True + + return False + def checkpoints(self, groups = None): for options in self.options(groups, True): - yield Job(options) + job = Job(options) + if self.jobfilter(job): + yield job def jobs(self, groups = None): for options in self.options(groups, False): - yield Job(options) + job = Job(options) + if self.jobfilter(job): + yield job def alljobs(self, groups = None): for options in self.options(groups, True): diff --git a/util/stats/barchart.py b/util/stats/barchart.py index 19cccb58a..3f202d9bf 100644 --- a/util/stats/barchart.py +++ b/util/stats/barchart.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005 The Regents of The University of Michigan +# Copyright (c) 2005-2006 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ import matplotlib, pylab from matplotlib.font_manager import FontProperties from matplotlib.numerix import array, arange, reshape, shape, transpose, zeros from matplotlib.numerix import Float +from matplotlib.ticker import NullLocator matplotlib.interactive(False) @@ -120,9 +121,6 @@ class BarChart(ChartOptions): if self.chartdata is None: raise AttributeError, "Data not set for bar chart!" - self.figure = pylab.figure(figsize=self.chart_size) - self.axes = self.figure.add_axes(self.figure_size) - dim = len(shape(self.inputdata)) cshape = shape(self.chartdata) if dim == 1: @@ -139,6 +137,31 @@ class BarChart(ChartOptions): colors = array(colors) + self.figure = pylab.figure(figsize=self.chart_size) + + outer_axes = None + inner_axes = None + if self.xsubticks is not None: + color = self.figure.get_facecolor() + self.metaaxes = self.figure.add_axes(self.figure_size, axisbg=color, frameon=False) + for tick in self.metaaxes.xaxis.majorTicks: + tick.tick1On = False + tick.tick2On = False + self.metaaxes.set_yticklabels([]) + self.metaaxes.set_yticks([]) + size = [0] * 4 + size[0] = self.figure_size[0] + size[1] = self.figure_size[1] + .05 + size[2] = self.figure_size[2] + size[3] = self.figure_size[3] - .05 + self.axes = self.figure.add_axes(size) + outer_axes = self.metaaxes + inner_axes = self.axes + else: + self.axes = self.figure.add_axes(self.figure_size) + outer_axes = self.axes + inner_axes = self.axes + bars_in_group = len(self.chartdata) if bars_in_group < 5: width = 1.0 / ( bars_in_group + 1) @@ -156,28 +179,35 @@ class BarChart(ChartOptions): ind = arange(len(bardata)) + i * width + center bar = self.axes.bar(ind, bardata, width, bottom=bottom, color=colors[i][j]) + if dim != 1: + self.metaaxes.bar(ind, [0] * len(bardata), width) stack.append(bar) bottom += bardata bars.append(stack) if self.xlabel is not None: - self.axes.set_xlabel(self.xlabel) + outer_axes.set_xlabel(self.xlabel) if self.ylabel is not None: - self.axes.set_ylabel(self.ylabel) + inner_axes.set_ylabel(self.ylabel) if self.yticks is not None: ymin, ymax = self.axes.get_ylim() nticks = float(len(self.yticks)) ticks = arange(nticks) / (nticks - 1) * (ymax - ymin) + ymin - self.axes.set_yticks(ticks) - self.axes.set_yticklabels(self.yticks) + inner_axes.set_yticks(ticks) + inner_axes.set_yticklabels(self.yticks) elif self.ylim is not None: - self.axes.set_ylim(self.ylim) + self.inner_axes.set_ylim(self.ylim) if self.xticks is not None: - self.axes.set_xticks(arange(cshape[2]) + .5) - self.axes.set_xticklabels(self.xticks) + outer_axes.set_xticks(arange(cshape[2]) + .5) + outer_axes.set_xticklabels(self.xticks) + + if self.xsubticks is not None: + inner_axes.set_xticks(arange((cshape[0] + 1)*cshape[2])*width + 2*center) + self.xsubticks.append('') + inner_axes.set_xticklabels(self.xsubticks * cshape[2], fontsize=8) if self.legend is not None: if dim == 1: @@ -220,7 +250,6 @@ class BarChart(ChartOptions): f.close() - if __name__ == '__main__': from random import randrange import random, sys @@ -252,6 +281,9 @@ if __name__ == '__main__': chart1.legend = [ 'x%d' % x for x in xrange(myshape[-1]) ] chart1.xticks = [ 'xtick%d' % x for x in xrange(myshape[0]) ] chart1.title = 'this is the title' + chart1.figure_size = [0.1, 0.2, 0.7, 0.85 ] + if len(myshape) > 2: + chart1.xsubticks = [ '%d' % x for x in xrange(myshape[1]) ] chart1.graph() chart1.savefig('/tmp/test1.png') chart1.savefig('/tmp/test1.ps') @@ -266,4 +298,4 @@ if __name__ == '__main__': chart2.savefig('/tmp/test2.png') chart2.savefig('/tmp/test2.ps') - #pylab.show() + pylab.myshow() diff --git a/util/stats/chart.py b/util/stats/chart.py index 1e301cb58..095620172 100644 --- a/util/stats/chart.py +++ b/util/stats/chart.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005 The Regents of The University of Michigan +# Copyright (c) 2005-2006 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,6 +38,7 @@ class ChartOptions(object): 'xlabel' : None, 'ylabel' : None, 'xticks' : None, + 'xsubticks' : None, 'yticks' : None, 'ylim' : None, } |