summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/SConscript146
-rw-r--r--arch/alpha/SConscript450
-rw-r--r--arch/alpha/alpha_linux_process.cc602
-rw-r--r--arch/alpha/alpha_linux_process.hh11
-rw-r--r--arch/alpha/alpha_memory.cc34
-rw-r--r--arch/alpha/alpha_memory.hh1
-rw-r--r--arch/alpha/alpha_tru64_process.cc1680
-rw-r--r--arch/alpha/alpha_tru64_process.hh12
-rw-r--r--arch/alpha/arguments.cc2
-rw-r--r--arch/alpha/ev5.hh4
-rw-r--r--arch/alpha/faults.cc77
-rw-r--r--arch/alpha/faults.hh153
-rw-r--r--arch/alpha/isa/branch.isa4
-rw-r--r--arch/alpha/isa/decoder.isa26
-rw-r--r--arch/alpha/isa/fp.isa18
-rw-r--r--arch/alpha/isa/main.isa37
-rw-r--r--arch/alpha/isa/mem.isa239
-rw-r--r--arch/alpha/isa/pal.isa8
-rw-r--r--arch/alpha/isa/unimp.isa4
-rw-r--r--arch/alpha/isa/unknown.isa2
-rw-r--r--arch/alpha/isa_traits.hh100
-rw-r--r--arch/alpha/stacktrace.cc3
-rw-r--r--arch/alpha/stacktrace.hh8
-rw-r--r--arch/alpha/vtophys.cc1
-rwxr-xr-xarch/isa_parser.py41
-rw-r--r--arch/isa_specific.hh62
-rw-r--r--arch/mips/SConscript83
-rw-r--r--arch/mips/isa/base.isa63
-rw-r--r--arch/mips/isa/bitfields.isa4
-rw-r--r--arch/mips/isa/decoder.isa1221
-rw-r--r--arch/mips/isa/formats.isa27
-rw-r--r--arch/mips/isa/formats/basic.isa5
-rw-r--r--arch/mips/isa/formats/branch.isa333
-rw-r--r--arch/mips/isa/formats/fp.isa27
-rw-r--r--arch/mips/isa/formats/int.isa21
-rw-r--r--arch/mips/isa/formats/mem.isa508
-rw-r--r--arch/mips/isa/formats/noop.isa103
-rw-r--r--arch/mips/isa/formats/unimp.isa165
-rw-r--r--arch/mips/isa/formats/unknown.isa52
-rw-r--r--arch/mips/isa/formats/util.isa125
-rw-r--r--arch/mips/isa/main.isa12
-rw-r--r--arch/mips/isa/operands.isa15
-rw-r--r--arch/mips/isa_traits.hh8
-rw-r--r--arch/sparc/SConscript82
44 files changed, 3127 insertions, 3452 deletions
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 &section);
};
- 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 &reg_file,
+ void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
int regnum);
- static void restoreMachineReg(RegFile &regs, const AnyReg &reg,
+ void restoreMachineReg(RegFile &regs, const AnyReg &reg,
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 &section);
};
- 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')