summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConscript122
-rw-r--r--arch/alpha/SConscript487
-rw-r--r--arch/alpha/alpha_linux_process.cc151
-rw-r--r--arch/alpha/alpha_memory.cc38
-rw-r--r--arch/alpha/alpha_memory.hh5
-rw-r--r--arch/alpha/alpha_tru64_process.cc236
-rw-r--r--arch/alpha/ev5.cc80
-rw-r--r--arch/alpha/faults.cc77
-rw-r--r--arch/alpha/faults.hh153
-rw-r--r--arch/alpha/isa/branch.isa259
-rw-r--r--arch/alpha/isa/decoder.isa802
-rw-r--r--arch/alpha/isa/fp.isa300
-rw-r--r--arch/alpha/isa/int.isa128
-rw-r--r--arch/alpha/isa/main.isa435
-rw-r--r--arch/alpha/isa/mem.isa702
-rw-r--r--arch/alpha/isa/pal.isa271
-rw-r--r--arch/alpha/isa/unimp.isa165
-rw-r--r--arch/alpha/isa/unknown.isa52
-rw-r--r--arch/alpha/isa/util.isa112
-rw-r--r--arch/alpha/isa_desc2737
-rw-r--r--arch/alpha/isa_traits.hh6
-rwxr-xr-xarch/isa_parser.py826
-rw-r--r--arch/mips/SConscript81
-rw-r--r--arch/mips/isa/bitfields.isa52
-rw-r--r--arch/mips/isa/decoder.isa902
-rw-r--r--arch/mips/isa/formats.isa29
-rw-r--r--arch/mips/isa/formats/basic.isa65
-rw-r--r--arch/mips/isa/formats/branch.isa259
-rw-r--r--arch/mips/isa/formats/fp.isa131
-rw-r--r--arch/mips/isa/formats/int.isa70
-rw-r--r--arch/mips/isa/formats/mem.isa78
-rw-r--r--arch/mips/isa/formats/noop.isa134
-rw-r--r--arch/mips/isa/formats/tlbop.isa53
-rw-r--r--arch/mips/isa/formats/trap.isa53
-rw-r--r--arch/mips/isa/formats/unimp.isa165
-rw-r--r--arch/mips/isa/formats/unknown.isa52
-rw-r--r--arch/mips/isa/includes.isa40
-rw-r--r--arch/mips/isa/main.isa52
-rw-r--r--arch/mips/isa/operands.isa35
-rw-r--r--arch/mips/isa_traits.cc58
-rw-r--r--arch/mips/isa_traits.hh532
-rw-r--r--arch/sparc/SConscript82
-rw-r--r--arch/sparc/isa/base.isa82
-rw-r--r--arch/sparc/isa/bitfields.isa50
-rw-r--r--arch/sparc/isa/decoder.isa638
-rw-r--r--arch/sparc/isa/formats.isa19
-rw-r--r--arch/sparc/isa/formats/basic.isa65
-rw-r--r--arch/sparc/isa/formats/branch.isa66
-rw-r--r--arch/sparc/isa/formats/integerop.isa110
-rw-r--r--arch/sparc/isa/formats/mem.isa78
-rw-r--r--arch/sparc/isa/formats/noop.isa47
-rw-r--r--arch/sparc/isa/formats/trap.isa53
-rw-r--r--arch/sparc/isa/includes.isa40
-rw-r--r--arch/sparc/isa/main.isa52
-rw-r--r--arch/sparc/isa/operands.isa32
-rw-r--r--arch/sparc/isa_traits.hh532
-rw-r--r--base/intmath.hh16
-rw-r--r--base/loader/object_file.hh2
-rw-r--r--base/loader/symtab.hh2
-rw-r--r--base/sched_list.hh4
-rw-r--r--base/socket.cc3
-rw-r--r--build/SConstruct6
-rw-r--r--build/build_options/default/MIPS_SE2
-rw-r--r--build/build_options/default/SPARC_SE2
-rw-r--r--cpu/base.hh2
-rw-r--r--cpu/base_dyn_inst.cc32
-rw-r--r--cpu/base_dyn_inst.hh24
-rw-r--r--cpu/exec_context.cc2
-rw-r--r--cpu/exec_context.hh43
-rw-r--r--cpu/inst_seq.hh2
-rw-r--r--cpu/o3/alpha_cpu.hh42
-rw-r--r--cpu/o3/alpha_cpu_impl.hh29
-rw-r--r--cpu/o3/alpha_dyn_inst.hh14
-rw-r--r--cpu/o3/alpha_dyn_inst_impl.hh8
-rw-r--r--cpu/o3/commit_impl.hh4
-rw-r--r--cpu/o3/fetch.hh2
-rw-r--r--cpu/o3/fetch_impl.hh18
-rw-r--r--cpu/o3/inst_queue_impl.hh3
-rw-r--r--cpu/o3/regfile.hh19
-rw-r--r--cpu/ozone/cpu.hh54
-rw-r--r--cpu/simple/cpu.cc81
-rw-r--r--cpu/simple/cpu.hh16
-rw-r--r--cpu/static_inst.hh2
-rw-r--r--dev/alpha_console.cc14
-rw-r--r--dev/alpha_console.hh4
-rw-r--r--dev/baddev.cc8
-rw-r--r--dev/baddev.hh4
-rw-r--r--dev/disk_image.cc2
-rw-r--r--dev/ide_ctrl.cc14
-rw-r--r--dev/ide_ctrl.hh4
-rw-r--r--dev/ide_disk.cc2
-rw-r--r--dev/isa_fake.cc16
-rw-r--r--dev/isa_fake.hh4
-rw-r--r--dev/ns_gige.cc14
-rw-r--r--dev/ns_gige.hh7
-rw-r--r--dev/pciconfigall.cc18
-rw-r--r--dev/pciconfigall.hh4
-rw-r--r--dev/pcidev.cc32
-rw-r--r--dev/pcidev.hh40
-rw-r--r--dev/platform.hh2
-rw-r--r--dev/simple_disk.hh2
-rw-r--r--dev/sinic.cc28
-rw-r--r--dev/sinic.hh10
-rw-r--r--dev/tsunami_cchip.cc68
-rw-r--r--dev/tsunami_cchip.hh4
-rw-r--r--dev/tsunami_io.cc70
-rw-r--r--dev/tsunami_io.hh4
-rw-r--r--dev/tsunami_pchip.cc70
-rw-r--r--dev/tsunami_pchip.hh4
-rw-r--r--dev/uart.hh4
-rw-r--r--dev/uart8250.cc8
-rw-r--r--dev/uart8250.hh4
-rw-r--r--kern/freebsd/freebsd_system.cc2
-rw-r--r--kern/kernel_stats.cc6
-rw-r--r--kern/kernel_stats.hh10
-rw-r--r--kern/linux/linux_system.cc3
-rw-r--r--kern/linux/linux_threadinfo.hh2
-rw-r--r--kern/tru64/dump_mbuf.cc2
-rw-r--r--kern/tru64/mbuf.hh2
-rw-r--r--kern/tru64/tru64_events.cc2
-rw-r--r--kern/tru64/tru64_system.cc2
-rw-r--r--kern/tru64/tru64_system.hh2
-rw-r--r--sim/byteswap.hh146
-rw-r--r--sim/faults.cc36
-rw-r--r--sim/faults.hh59
-rw-r--r--sim/process.cc5
-rw-r--r--sim/process.hh2
-rw-r--r--sim/pseudo_inst.cc (renamed from arch/alpha/pseudo_inst.cc)42
-rw-r--r--sim/pseudo_inst.hh (renamed from arch/alpha/pseudo_inst.hh)19
-rw-r--r--sim/syscall_emul.cc10
-rw-r--r--sim/syscall_emul.hh78
-rw-r--r--sim/system.cc2
-rw-r--r--sim/vptr.hh (renamed from arch/alpha/vptr.hh)10
-rw-r--r--util/emacs/m5-c-style.el3
134 files changed, 10328 insertions, 3947 deletions
diff --git a/SConscript b/SConscript
index 677a06d1f..360f91b3a 100644
--- a/SConscript
+++ b/SConscript
@@ -43,15 +43,8 @@ Import('env')
###################################################
# Base sources used by all configurations.
-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('''
base/circlebuf.cc
base/copyright.cc
base/cprintf.cc
@@ -216,6 +209,7 @@ base_sources = Split('''
sim/configfile.cc
sim/debug.cc
sim/eventq.cc
+ sim/faults.cc
sim/main.cc
sim/param.cc
sim/profile.cc
@@ -229,6 +223,14 @@ base_sources = Split('''
sim/stat_control.cc
sim/trace_context.cc
''')
+# These are now included by the architecture specific SConscript
+# arch/alpha/decoder.cc
+# arch/alpha/alpha_o3_exec.cc
+# arch/alpha/fast_cpu_exec.cc
+# arch/alpha/simple_cpu_exec.cc
+# arch/alpha/full_cpu_exec.cc
+# arch/alpha/faults.cc
+# arch/alpha/isa_traits.cc
# MySql sources
mysql_sources = Split('''
@@ -238,14 +240,6 @@ mysql_sources = Split('''
# Full-system sources
full_system_sources = Split('''
- arch/alpha/alpha_memory.cc
- arch/alpha/arguments.cc
- arch/alpha/ev5.cc
- arch/alpha/osfpal.cc
- arch/alpha/pseudo_inst.cc
- arch/alpha/stacktrace.cc
- arch/alpha/vtophys.cc
-
base/crc.cc
base/inet.cc
base/remote_gdb.cc
@@ -299,8 +293,18 @@ full_system_sources = Split('''
mem/functional/physical.cc
sim/system.cc
+ sim/pseudo_inst.cc
''')
+# These are now included by the architecture specific SConscript
+# arch/alpha/alpha_memory.cc
+# arch/alpha/arguments.cc
+# arch/alpha/ev5.cc
+# arch/alpha/osfpal.cc
+# arch/alpha/pseudo_inst.cc
+# arch/alpha/stacktrace.cc
+# arch/alpha/vtophys.cc
+
# turbolaser encumbered sources
turbolaser_sources = Split('''
encumbered/dev/dma.cc
@@ -323,9 +327,6 @@ turbolaser_sources = Split('''
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
- arch/alpha/alpha_common_syscall_emul.cc
- arch/alpha/alpha_linux_process.cc
- arch/alpha/alpha_tru64_process.cc
cpu/memtest/memtest.cc
encumbered/eio/eio.cc
encumbered/eio/exolex.cc
@@ -334,33 +335,46 @@ syscall_emulation_sources = Split('''
sim/syscall_emul.cc
''')
+# These are now included by the architecture specific SConscript
+# arch/alpha/alpha_common_syscall_emul.cc
+# arch/alpha/alpha_linux_process.cc
+# arch/alpha/alpha_tru64_process.cc
+
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
''')
-
+# pseudo_inst.hh
+# isa_traits.hh
+# osfpal.hh
+# byte_swap.hh
+# alpha_common_syscall_emul.hh
+# vptr.hh
+# isa_fullsys_traits.hh
+
+# Set up bridging headers to the architecture specific versions
for f in targetarch_files:
- env.Command('targetarch/' + f, 'arch/alpha/' + f,
- '''echo '#include "arch/alpha/%s"' > $TARGET''' % f)
+ env.Command('targetarch/' + f, 'arch/%s/%s' % (env['TARGET_ISA'], f),
+ '''echo '#include "arch/%s/%s"' > $TARGET''' % (env['TARGET_ISA'], f))
+# Let the target architecture define what sources it needs
+arch_source = SConscript('arch/%s/SConscript' % env['TARGET_ISA'],
+ build_dir = 'build/%s/' % env['BUILD_DIR'],
+ exports = 'env', duplicate = False)
+
+# Add a flag defining what THE_ISA should be for all compilation
+env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
# Set up complete list of sources based on configuration.
-sources = base_sources
+sources = base_sources + arch_source
if env['FULL_SYSTEM']:
sources += full_system_sources
@@ -377,6 +391,27 @@ for opt in env.ExportOptions:
###################################################
#
+# Add an SCons scanner for ISA files
+#
+###################################################
+import SCons.Scanner
+
+def ISAScan():
+ return SCons.Scanner.Classic("ISAScan",
+ "$ISASUFFIXES",
+ "SRCDIR",
+ '^[ \t]*##[ \t]*include[ \t]*"([^>"]+)"')
+
+def ISAPath(env, dir, target=None, source=None, a=None):
+ return (Dir(env['SRCDIR']), Dir('.'))
+
+iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"],
+ path_function = ISAPath)
+env.Append(SCANNERS = iscan)
+
+
+###################################################
+#
# Special build rules.
#
###################################################
@@ -388,15 +423,24 @@ env.Command(Split('base/traceflags.hh base/traceflags.cc'),
'python $SOURCE $TARGET.base')
# several files are generated from arch/$TARGET_ISA/isa_desc.
-env.Command(Split('''arch/alpha/decoder.cc
- arch/alpha/decoder.hh
- arch/alpha/alpha_o3_exec.cc
- arch/alpha/fast_cpu_exec.cc
- arch/alpha/simple_cpu_exec.cc
- arch/alpha/full_cpu_exec.cc'''),
- Split('''arch/alpha/isa_desc
- arch/isa_parser.py'''),
- '$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/alpha')
+env.Command(Split('''
+ arch/%s/decoder.cc
+ arch/%s/decoder.hh
+ arch/%s/alpha_o3_exec.cc
+ arch/%s/fast_cpu_exec.cc
+ arch/%s/simple_cpu_exec.cc
+ arch/%s/full_cpu_exec.cc''' %
+ (env['TARGET_ISA'],
+ env['TARGET_ISA'],
+ env['TARGET_ISA'],
+ env['TARGET_ISA'],
+ env['TARGET_ISA'],
+ env['TARGET_ISA'])),
+ Split('''
+ arch/%s/isa/main.isa
+ arch/isa_parser.py''' %
+ env['TARGET_ISA']),
+ '$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/%s' % env['TARGET_ISA'])
# libelf build is described in its own SConscript file.
diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript
new file mode 100644
index 000000000..8bf408c06
--- /dev/null
+++ b/arch/alpha/SConscript
@@ -0,0 +1,487 @@
+# -*- 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
+
+# This file defines how to build a particular configuration of M5
+# based on variable settings in the 'env' build environment.
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# 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/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
+ ''')
+
+# 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
+ ''')
+# 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
+
+if env['FULL_SYSTEM']:
+ sources += arch_full_system_sources
+ if env['ALPHA_TLASER']:
+ sources += arch_turbolaser_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]
+
+# 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]
+
+# "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]
+
+# 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 83b0b5e5a..fb5e32e63 100644
--- a/arch/alpha/alpha_linux_process.cc
+++ b/arch/alpha/alpha_linux_process.cc
@@ -42,6 +42,7 @@
#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/syscall_emul.hh"
#include "sim/root.hh" // for curTick & ticksPerSecond
@@ -70,6 +71,15 @@ class Linux {
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
@@ -138,7 +148,7 @@ class Linux {
uint64_t st_mtime_nsec;
uint64_t tgt_st_ctime;
uint64_t st_ctime_nsec;
- int64_t __unused[3];
+ int64_t ___unused[3];
};
/// Length of strings in struct utsname (plus 1 for null char).
@@ -169,18 +179,18 @@ class Linux {
/// Resource enumeration for getrlimit().
enum rlimit_resources {
- RLIMIT_CPU = 0,
- RLIMIT_FSIZE = 1,
- RLIMIT_DATA = 2,
- RLIMIT_STACK = 3,
- RLIMIT_CORE = 4,
- RLIMIT_RSS = 5,
- RLIMIT_NOFILE = 6,
- RLIMIT_AS = 7,
- RLIMIT_VMEM = 7,
- RLIMIT_NPROC = 8,
- RLIMIT_MEMLOCK = 9,
- RLIMIT_LOCKS = 10
+ 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.
@@ -207,9 +217,9 @@ class Linux {
//@{
/// For getrusage().
- static const int RUSAGE_SELF = 0;
- static const int RUSAGE_CHILDREN = -1;
- static const int RUSAGE_BOTH = -2;
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
+ static const int TGT_RUSAGE_BOTH = -2;
//@}
/// For getrusage().
@@ -235,59 +245,98 @@ class Linux {
/// 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, struct stat *host)
+ copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
{
TypedBufferArg<Linux::tgt_stat> tgt(addr);
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
+ 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, Addr addr, struct stat64 *host)
+ copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host)
{
TypedBufferArg<Linux::tgt_stat64> tgt(addr);
- // XXX byteswaps
- tgt->st_dev = host->st_dev;
+ // 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 = host->st_ino;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_blocks = host->st_blocks;
-
- tgt->st_mode = host->st_mode;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_blksize = host->st_blksize;
- tgt->st_nlink = host->st_nlink;
- tgt->tgt_st_atime = host->st_atime;
- tgt->tgt_st_mtime = host->st_mtime;
- tgt->tgt_st_ctime = host->st_ctime;
-#ifdef STAT_HAVE_NSEC
- tgt->st_atime_nsec = host->st_atime_nsec;
- tgt->st_mtime_nsec = host->st_mtime_nsec;
- tgt->st_ctime_nsec = host->st_ctime_nsec;
+ 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);
}
@@ -355,7 +404,7 @@ class Linux {
// 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", *(uint64_t*)fpcr);
+ " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
return 0;
}
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc
index 8dda4d9c4..615ce92a4 100644
--- a/arch/alpha/alpha_memory.cc
+++ b/arch/alpha/alpha_memory.cc
@@ -303,7 +303,7 @@ AlphaITB::fault(Addr pc, ExecContext *xc) const
}
-Fault
+Fault *
AlphaITB::translate(MemReqPtr &req) const
{
InternalProcReg *ipr = req->xc->regs.ipr;
@@ -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;
}
///////////////////////////////////////////////////////////////////////
@@ -493,7 +493,7 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
}
}
-Fault
+Fault *
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
RegFile *regs = &req->xc->regs;
@@ -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..849063f59 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"
@@ -93,7 +94,7 @@ class AlphaITB : public AlphaTLB
AlphaITB(const std::string &name, int size);
virtual void regStats();
- Fault translate(MemReqPtr &req) const;
+ Fault * translate(MemReqPtr &req) const;
};
class AlphaDTB : public AlphaTLB
@@ -119,7 +120,7 @@ class AlphaDTB : public AlphaTLB
AlphaDTB(const std::string &name, int size);
virtual void regStats();
- Fault translate(MemReqPtr &req, bool write) const;
+ Fault * translate(MemReqPtr &req, bool write) const;
};
#endif // __ALPHA_MEMORY_HH__
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc
index b7a1c7d59..5c24adad9 100644
--- a/arch/alpha/alpha_tru64_process.cc
+++ b/arch/alpha/alpha_tru64_process.cc
@@ -28,7 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
-#if defined(__OpenBSD__)
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/mount.h>
#else
@@ -41,6 +41,7 @@
#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"
@@ -259,15 +260,15 @@ class Tru64 {
/// Resource enumeration for getrlimit().
enum rlimit_resources {
- RLIMIT_CPU = 0,
- RLIMIT_FSIZE = 1,
- RLIMIT_DATA = 2,
- RLIMIT_STACK = 3,
- RLIMIT_CORE = 4,
- RLIMIT_RSS = 5,
- RLIMIT_NOFILE = 6,
- RLIMIT_AS = 7,
- RLIMIT_VMEM = 7
+ 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.
@@ -319,9 +320,9 @@ class Tru64 {
//@{
/// For getrusage().
- static const int RUSAGE_THREAD = 1;
- static const int RUSAGE_SELF = 0;
- static const int RUSAGE_CHILDREN = -1;
+ static const int TGT_RUSAGE_THREAD = 1;
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
//@}
/// For getrusage().
@@ -541,19 +542,19 @@ class Tru64 {
{
TypedBufferArg<T> tgt(addr);
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
+ 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);
}
@@ -567,17 +568,19 @@ class Tru64 {
{
TypedBufferArg<T> tgt(addr);
-#if defined(__OpenBSD__)
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
tgt->f_type = 0;
#else
- tgt->f_type = host->f_type;
+ tgt->f_type = htog(host->f_type);
#endif
- tgt->f_bsize = host->f_bsize;
- tgt->f_blocks = host->f_blocks;
- tgt->f_bfree = host->f_bfree;
- tgt->f_bavail = host->f_bavail;
- tgt->f_files = host->f_files;
- tgt->f_ffree = host->f_ffree;
+ 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);
@@ -622,19 +625,19 @@ class Tru64 {
{
TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
+ 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);
}
@@ -673,21 +676,21 @@ class Tru64 {
case Tru64::GSI_MAX_CPU: {
TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
- *max_cpu = process->numCpus();
+ *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 = process->numCpus();
+ *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 = 1024 * 1024; // physical memory in KB
+ *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
physmem.copyOut(xc->mem);
return 1;
}
@@ -695,15 +698,15 @@ class Tru64 {
case Tru64::GSI_CPU_INFO: {
TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
- infop->current_cpu = 0;
- infop->cpus_in_box = process->numCpus();
- infop->cpu_type = 57;
- infop->ncpus = process->numCpus();
- int cpumask = (1 << process->numCpus()) - 1;
- infop->cpus_present = infop->cpus_running = cpumask;
- infop->cpu_binding = 0;
- infop->cpu_ex_binding = 0;
- infop->mhz = 667;
+ 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;
@@ -711,7 +714,7 @@ class Tru64 {
case Tru64::GSI_PROC_TYPE: {
TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
- *proc_type = 11;
+ *proc_type = htog((uint64_t)11);
proc_type.copyOut(xc->mem);
return 1;
}
@@ -727,7 +730,7 @@ class Tru64 {
case Tru64::GSI_CLK_TCK: {
TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
- *clk_hz = 1024;
+ *clk_hz = htog((uint64_t)1024);
clk_hz.copyOut(xc->mem);
return 1;
}
@@ -823,7 +826,7 @@ class Tru64 {
// just pass basep through uninterpreted.
TypedBufferArg<int64_t> basep(tgt_basep);
basep.copyIn(xc->mem);
- long host_basep = (off_t)*basep;
+ long host_basep = (off_t)htog((int64_t)*basep);
int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
// check for error
@@ -857,7 +860,7 @@ class Tru64 {
delete [] host_buf;
- *basep = host_basep;
+ *basep = htog((int64_t)host_basep);
basep.copyOut(xc->mem);
return tgt_buf_ptr - tgt_buf;
@@ -878,14 +881,14 @@ class Tru64 {
// 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 = sc->sc_pc;
+ regs->npc = htog(sc->sc_pc);
for (int i = 0; i < 31; ++i) {
- regs->intRegFile[i] = sc->sc_regs[i];
- regs->floatRegFile.q[i] = sc->sc_fpregs[i];
+ regs->intRegFile[i] = htog(sc->sc_regs[i]);
+ regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]);
}
- regs->miscRegs.fpcr = sc->sc_fpcr;
+ regs->miscRegs.fpcr = htog(sc->sc_fpcr);
return 0;
}
@@ -908,15 +911,15 @@ class Tru64 {
TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
const int clk_hz = one_million;
- elp->si_user = curTick / (Clock::Frequency / clk_hz);
- elp->si_nice = 0;
- elp->si_sys = 0;
- elp->si_idle = 0;
- elp->wait = 0;
- elp->si_hz = clk_hz;
- elp->si_phz = clk_hz;
- elp->si_boottime = seconds_since_epoch; // seconds since epoch?
- elp->si_max_procs = process->numCpus();
+ 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;
}
@@ -951,9 +954,10 @@ class Tru64 {
// if the user chose an address, just let them have it. Otherwise
// pick one for them.
- if (argp->address == 0) {
- argp->address = process->next_thread_stack_base;
- int stack_size = (argp->rsize + argp->ysize + argp->gsize);
+ 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);
}
@@ -977,14 +981,14 @@ class Tru64 {
attrp.copyIn(xc->mem);
- if (attrp->nxm_version != NXM_LIB_VERSION) {
+ 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 (attrp->flags != Tru64::NXM_TASK_INIT_VP) {
+ 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();
@@ -1011,10 +1015,10 @@ class Tru64 {
// 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 = process->numCpus();
- config->nxm_nrads = 1; // only one RAD in our system!
- config->nxm_slot_state = slot_state_addr;
- config->nxm_rad[0] = rad_state_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);
@@ -1023,6 +1027,8 @@ class Tru64 {
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;
}
@@ -1040,24 +1046,24 @@ class Tru64 {
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 = 0;
- ssp->nxm_u.sig = 0;
- ssp->nxm_u.flags = 0;
- ssp->nxm_u.cancel_state = 0;
+ 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 = 0;
+ ssp->nxm_bits = htog(0);
ssp->nxm_quantum = attrp->nxm_quantum;
ssp->nxm_set_quantum = attrp->nxm_quantum;
- ssp->nxm_sysevent = 0;
+ ssp->nxm_sysevent = htog(0);
if (i == 0) {
uint64_t uniq = xc->regs.miscRegs.uniq;
- ssp->nxm_u.pth_id = uniq + attrp->nxm_uniq_offset;
- ssp->nxm_u.nxm_active = uniq | 1;
+ 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 = 0;
- ssp->nxm_u.nxm_active = 0;
+ ssp->nxm_u.pth_id = htog(0);
+ ssp->nxm_u.nxm_active = htog(0);
}
}
@@ -1066,7 +1072,7 @@ class Tru64 {
//
// copy pointer to shared config area out to user
//
- *configptr_ptr = config_addr;
+ *configptr_ptr = htog(config_addr);
configptr_ptr.copyOut(xc->mem);
// Register this as a valid address range with the process
@@ -1083,13 +1089,13 @@ class Tru64 {
{
memset(&ec->regs, 0, sizeof(ec->regs));
- ec->regs.intRegFile[ArgumentReg0] = attrp->registers.a0;
- ec->regs.intRegFile[27/*t12*/] = attrp->registers.pc;
- ec->regs.intRegFile[StackPointerReg] = attrp->registers.sp;
+ 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 = attrp->registers.pc;
- ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
+ ec->regs.pc = gtoh(attrp->registers.pc);
+ ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(MachInst);
ec->activate();
}
@@ -1106,7 +1112,7 @@ class Tru64 {
// get attribute args
attrp.copyIn(xc->mem);
- if (attrp->version != NXM_LIB_VERSION) {
+ if (gtoh(attrp->version) != NXM_LIB_VERSION) {
cerr << "nxm_thread_create: thread library version mismatch! "
<< "got " << attrp->version
<< ", expected " << NXM_LIB_VERSION << endl;
@@ -1131,28 +1137,28 @@ class Tru64 {
rad_state_size);
rad_state.copyIn(xc->mem);
- uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset;
+ uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
- if (attrp->type == Tru64::NXM_TYPE_MANAGER) {
+ 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 = 99;
+ *kidp = htog(99);
kidp.copyOut(xc->mem);
return 0;
- } else if (attrp->type == Tru64::NXM_TYPE_VP) {
+ } 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 (ssp->nxm_u.nxm_active != 0)
+ 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 = uniq_val | 1;
+ ssp->nxm_u.nxm_active = htog(uniq_val | 1);
rad_state.copyOut(xc->mem);
@@ -1172,6 +1178,8 @@ class Tru64 {
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);
@@ -1187,7 +1195,7 @@ class Tru64 {
// This is supposed to be a port number, but we'll try
// and get away with just sticking the thread index
// here.
- *kidp = thread_index;
+ *kidp = htog(thread_index);
kidp.copyOut(xc->mem);
return 0;
@@ -1319,9 +1327,9 @@ class Tru64 {
lockp.copyIn(xc->mem);
- if (*lockp == 0) {
+ if (gtoh(*lockp) == 0) {
// lock is free: grab it
- *lockp = 1;
+ *lockp = htog(1);
lockp.copyOut(xc->mem);
} else {
// lock is busy: disable until free
@@ -1374,9 +1382,9 @@ class Tru64 {
lockp.copyIn(xc->mem);
- if (*lockp == 0) {
+ if (gtoh(*lockp) == 0) {
// lock is free: grab it
- *lockp = 1;
+ *lockp = htog(1);
lockp.copyOut(xc->mem);
return 0;
} else {
@@ -1433,7 +1441,7 @@ class Tru64 {
// user is supposed to acquire lock before entering
lockp.copyIn(xc->mem);
- assert(*lockp != 0);
+ assert(gtoh(*lockp) != 0);
m5_unlock_mutex(lock_addr, process, xc);
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 125affd03..72f48bfb2 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -76,7 +76,7 @@ AlphaISA::initCPU(RegFile *regs)
// CPU comes up with PAL regs enabled
swap_palshadow(regs, true);
- regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault];
+ regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr(ResetFault);
regs->npc = regs->pc + sizeof(MachInst);
}
@@ -84,25 +84,15 @@ AlphaISA::initCPU(RegFile *regs)
//
// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE
//
-Addr
-AlphaISA::fault_addr[Num_Faults] = {
- 0x0000, /* No_Fault */
- 0x0001, /* Reset_Fault */
- 0x0401, /* Machine_Check_Fault */
- 0x0501, /* Arithmetic_Fault */
- 0x0101, /* Interrupt_Fault */
- 0x0201, /* Ndtb_Miss_Fault */
- 0x0281, /* Pdtb_Miss_Fault */
- 0x0301, /* Alignment_Fault */
- 0x0381, /* DTB_Fault_Fault */
- 0x0381, /* DTB_Acv_Fault */
- 0x0181, /* ITB_Miss_Fault */
- 0x0181, /* ITB_Fault_Fault */
- 0x0081, /* ITB_Acv_Fault */
- 0x0481, /* Unimplemented_Opcode_Fault */
- 0x0581, /* Fen_Fault */
- 0x2001, /* Pal_Fault */
- 0x0501, /* Integer_Overflow_Fault: maps to Arithmetic_Fault */
+const Addr
+AlphaISA::fault_addr(Fault * fault)
+{
+ //Check for the system wide faults
+ if(fault == NoFault) return 0x0000;
+ else if(fault == MachineCheckFault) return 0x0401;
+ else if(fault == AlignmentFault) return 0x0301;
+ //Deal with the alpha specific faults
+ return ((AlphaFault*)fault)->vect;
};
const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
@@ -168,7 +158,7 @@ AlphaISA::processInterrupts(CPU *cpu)
if (ipl && ipl > ipr[IPR_IPLR]) {
ipr[IPR_ISR] = summary;
ipr[IPR_INTID] = ipl;
- cpu->trap(Interrupt_Fault);
+ cpu->trap(InterruptFault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
ipr[IPR_IPLR], ipl, summary);
}
@@ -187,25 +177,25 @@ AlphaISA::zeroRegisters(CPU *cpu)
}
void
-ExecContext::ev5_trap(Fault fault)
+ExecContext::ev5_trap(Fault * fault)
{
- DPRINTF(Fault, "Fault %s at PC: %#x\n", FaultName(fault), regs.pc);
- cpu->recordEvent(csprintf("Fault %s", FaultName(fault)));
+ DPRINTF(Fault, "Fault %s at PC: %#x\n", fault->name, regs.pc);
+ cpu->recordEvent(csprintf("Fault %s", fault->name));
assert(!misspeculating());
kernelStats->fault(fault);
- if (fault == Arithmetic_Fault)
+ if (fault == ArithmeticFault)
panic("Arithmetic traps are unimplemented!");
AlphaISA::InternalProcReg *ipr = regs.ipr;
// exception restart address
- if (fault != Interrupt_Fault || !inPalMode())
+ if (fault != InterruptFault || !inPalMode())
ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
- if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
- fault == Interrupt_Fault && !inPalMode() */) {
+ if (fault == PalFault || fault == ArithmeticFault /* ||
+ fault == InterruptFault && !inPalMode() */) {
// traps... skip faulting instruction
ipr[AlphaISA::IPR_EXC_ADDR] += 4;
}
@@ -213,22 +203,22 @@ ExecContext::ev5_trap(Fault fault)
if (!inPalMode())
AlphaISA::swap_palshadow(&regs, true);
- regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
+ regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr(fault);
regs.npc = regs.pc + sizeof(MachInst);
}
void
-AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
+AlphaISA::intr_post(RegFile *regs, Fault * fault, Addr pc)
{
InternalProcReg *ipr = regs->ipr;
- bool use_pc = (fault == No_Fault);
+ bool use_pc = (fault == NoFault);
- if (fault == Arithmetic_Fault)
+ if (fault == ArithmeticFault)
panic("arithmetic faults NYI...");
// compute exception restart address
- if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) {
+ if (use_pc || fault == PalFault || fault == ArithmeticFault) {
// traps... skip faulting instruction
ipr[IPR_EXC_ADDR] = regs->pc + 4;
} else {
@@ -238,20 +228,20 @@ AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
// jump to expection address (PAL PC bit set here as well...)
if (!use_pc)
- regs->npc = ipr[IPR_PAL_BASE] + fault_addr[fault];
+ regs->npc = ipr[IPR_PAL_BASE] + fault_addr(fault);
else
regs->npc = ipr[IPR_PAL_BASE] + pc;
// that's it! (orders of magnitude less painful than x86)
}
-Fault
+Fault *
ExecContext::hwrei()
{
uint64_t *ipr = regs.ipr;
if (!inPalMode())
- return Unimplemented_Opcode_Fault;
+ return UnimplementedOpcodeFault;
setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
@@ -265,11 +255,11 @@ ExecContext::hwrei()
}
// FIXME: XXX check for interrupts? XXX
- return No_Fault;
+ return NoFault;
}
uint64_t
-ExecContext::readIpr(int idx, Fault &fault)
+ExecContext::readIpr(int idx, Fault * &fault)
{
uint64_t *ipr = regs.ipr;
uint64_t retval = 0; // return value, default 0
@@ -363,12 +353,12 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_DTB_IAP:
case AlphaISA::IPR_ITB_IA:
case AlphaISA::IPR_ITB_IAP:
- fault = Unimplemented_Opcode_Fault;
+ fault = UnimplementedOpcodeFault;
break;
default:
// invalid IPR
- fault = Unimplemented_Opcode_Fault;
+ fault = UnimplementedOpcodeFault;
break;
}
@@ -380,14 +370,14 @@ ExecContext::readIpr(int idx, Fault &fault)
int break_ipl = -1;
#endif
-Fault
+Fault *
ExecContext::setIpr(int idx, uint64_t val)
{
uint64_t *ipr = regs.ipr;
uint64_t old;
if (misspeculating())
- return No_Fault;
+ return NoFault;
switch (idx) {
case AlphaISA::IPR_PALtemp0:
@@ -533,7 +523,7 @@ ExecContext::setIpr(int idx, uint64_t val)
case AlphaISA::IPR_ITB_PTE_TEMP:
case AlphaISA::IPR_DTB_PTE_TEMP:
// read-only registers
- return Unimplemented_Opcode_Fault;
+ return UnimplementedOpcodeFault;
case AlphaISA::IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT:
@@ -635,11 +625,11 @@ ExecContext::setIpr(int idx, uint64_t val)
default:
// invalid IPR
- return Unimplemented_Opcode_Fault;
+ return UnimplementedOpcodeFault;
}
// no error...
- return No_Fault;
+ return NoFault;
}
/**
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc
index 3aecf029d..e05b3fe59 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..06605861a 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 Fault
+{
+ public:
+ AlphaFault(char * newName, int newId, Addr newVect)
+ : Fault(newName, newId), vect(newVect)
+ {;}
+
+ TheISA::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
new file mode 100644
index 000000000..e9c790c53
--- /dev/null
+++ b/arch/alpha/isa/branch.isa
@@ -0,0 +1,259 @@
+// -*- 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 {{
+
+ /**
+ * 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 AlphaStaticInst
+ {
+ 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)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(BRDISP << 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 Alpha 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(BRDISP)
+ {
+ }
+
+ Addr branchTarget(ExecContext *xc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::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)
+ {
+ 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
+ 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 template JumpOrBranchDecode {{
+ return (RA == 31)
+ ? (StaticInst<AlphaISA> *)new %(class_name)s(machInst)
+ : (StaticInst<AlphaISA> *)new %(class_name)sAndLink(machInst);
+}};
+
+def format CondBranch(code) {{
+ code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\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)
+}};
+
+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 format UncondBranch(*flags) {{
+ flags += ('IsUncondControl', 'IsDirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+}};
+
+def format Jump(*flags) {{
+ flags += ('IsUncondControl', 'IsIndirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+}};
+
+
diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa
new file mode 100644
index 000000000..37b15416b
--- /dev/null
+++ b/arch/alpha/isa/decoder.isa
@@ -0,0 +1,802 @@
+// -*- 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.
+
+decode OPCODE default Unknown::unknown() {
+
+ format LoadAddress {
+ 0x08: lda({{ Ra = Rb + disp; }});
+ 0x09: ldah({{ Ra = Rb + (disp << 16); }});
+ }
+
+ format LoadOrNop {
+ 0x0a: ldbu({{ Ra.uq = Mem.ub; }});
+ 0x0c: ldwu({{ Ra.uq = Mem.uw; }});
+ 0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
+ 0x23: ldt({{ Fa = Mem.df; }});
+ 0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
+ 0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
+ 0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
+ {{ fault = xc->copySrcTranslate(EA); }},
+ inst_flags = [IsMemRef, IsLoad, IsCopy]);
+ }
+
+ format LoadOrPrefetch {
+ 0x28: ldl({{ Ra.sl = Mem.sl; }});
+ 0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
+ // IsFloating flag on lds gets the prefetch to disassemble
+ // using f31 instead of r31... funcitonally it's unnecessary
+ 0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
+ pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
+ }
+
+ format Store {
+ 0x0e: stb({{ Mem.ub = Ra<7:0>; }});
+ 0x0d: stw({{ Mem.uw = Ra<15:0>; }});
+ 0x2c: stl({{ Mem.ul = Ra<31:0>; }});
+ 0x2d: stq({{ Mem.uq = Ra.uq; }});
+ 0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
+ 0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
+ 0x27: stt({{ Mem.df = Fa; }});
+ 0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
+ {{ fault = xc->copy(EA); }},
+ inst_flags = [IsMemRef, IsStore, IsCopy]);
+ }
+
+ format StoreCond {
+ 0x2e: stl_c({{ Mem.ul = Ra<31:0>; }},
+ {{
+ uint64_t tmp = write_result;
+ // see stq_c
+ Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
+ }}, mem_flags = LOCKED);
+ 0x2f: stq_c({{ Mem.uq = Ra; }},
+ {{
+ uint64_t tmp = write_result;
+ // If the write operation returns 0 or 1, then
+ // this was a conventional store conditional,
+ // and the value indicates the success/failure
+ // of the operation. If another value is
+ // returned, then this was a Turbolaser
+ // mailbox access, and we don't update the
+ // result register at all.
+ Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
+ }}, mem_flags = LOCKED);
+ }
+
+ format IntegerOperate {
+
+ 0x10: decode INTFUNC { // integer arithmetic operations
+
+ 0x00: addl({{ Rc.sl = Ra.sl + Rb_or_imm.sl; }});
+ 0x40: addlv({{
+ uint32_t tmp = Ra.sl + Rb_or_imm.sl;
+ // 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 = IntegerOverflowFault;
+ Rc.sl = tmp;
+ }});
+ 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }});
+ 0x12: s8addl({{ Rc.sl = (Ra.sl << 3) + Rb_or_imm.sl; }});
+
+ 0x20: addq({{ Rc = Ra + Rb_or_imm; }});
+ 0x60: addqv({{
+ uint64_t tmp = Ra + Rb_or_imm;
+ // 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 = IntegerOverflowFault;
+ Rc = tmp;
+ }});
+ 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }});
+ 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }});
+
+ 0x09: subl({{ Rc.sl = Ra.sl - Rb_or_imm.sl; }});
+ 0x49: sublv({{
+ uint32_t tmp = Ra.sl - Rb_or_imm.sl;
+ // signed overflow detection is same as for add,
+ // except we need to look at the *complemented*
+ // 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 = IntegerOverflowFault;
+ Rc.sl = tmp;
+ }});
+ 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }});
+ 0x1b: s8subl({{ Rc.sl = (Ra.sl << 3) - Rb_or_imm.sl; }});
+
+ 0x29: subq({{ Rc = Ra - Rb_or_imm; }});
+ 0x69: subqv({{
+ uint64_t tmp = Ra - Rb_or_imm;
+ // signed overflow detection is same as for add,
+ // except we need to look at the *complemented*
+ // 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 = IntegerOverflowFault;
+ Rc = tmp;
+ }});
+ 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }});
+ 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }});
+
+ 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }});
+ 0x6d: cmple({{ Rc = (Ra.sq <= Rb_or_imm.sq); }});
+ 0x4d: cmplt({{ Rc = (Ra.sq < Rb_or_imm.sq); }});
+ 0x3d: cmpule({{ Rc = (Ra.uq <= Rb_or_imm.uq); }});
+ 0x1d: cmpult({{ Rc = (Ra.uq < Rb_or_imm.uq); }});
+
+ 0x0f: cmpbge({{
+ int hi = 7;
+ int lo = 0;
+ uint64_t tmp = 0;
+ for (int i = 0; i < 8; ++i) {
+ tmp |= (Ra.uq<hi:lo> >= Rb_or_imm.uq<hi:lo>) << i;
+ hi += 8;
+ lo += 8;
+ }
+ Rc = tmp;
+ }});
+ }
+
+ 0x11: decode INTFUNC { // integer logical operations
+
+ 0x00: and({{ Rc = Ra & Rb_or_imm; }});
+ 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }});
+ 0x20: bis({{ Rc = Ra | Rb_or_imm; }});
+ 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }});
+ 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }});
+ 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }});
+
+ // conditional moves
+ 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }});
+ 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }});
+ 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }});
+ 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }});
+ 0x44: cmovlt({{ Rc = (Ra.sq < 0) ? Rb_or_imm : Rc; }});
+ 0x46: cmovge({{ Rc = (Ra.sq >= 0) ? Rb_or_imm : Rc; }});
+ 0x64: cmovle({{ Rc = (Ra.sq <= 0) ? Rb_or_imm : Rc; }});
+ 0x66: cmovgt({{ Rc = (Ra.sq > 0) ? Rb_or_imm : Rc; }});
+
+ // For AMASK, RA must be R31.
+ 0x61: decode RA {
+ 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }});
+ }
+
+ // For IMPLVER, RA must be R31 and the B operand
+ // must be the immediate value 1.
+ 0x6c: decode RA {
+ 31: decode IMM {
+ 1: decode INTIMM {
+ // return EV5 for FULL_SYSTEM and EV6 otherwise
+ 1: implver({{
+#if FULL_SYSTEM
+ Rc = 1;
+#else
+ Rc = 2;
+#endif
+ }});
+ }
+ }
+ }
+
+#if FULL_SYSTEM
+ // The mysterious 11.25...
+ 0x25: WarnUnimpl::eleven25();
+#endif
+ }
+
+ 0x12: decode INTFUNC {
+ 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }});
+ 0x34: srl({{ Rc = Ra.uq >> Rb_or_imm<5:0>; }});
+ 0x3c: sra({{ Rc = Ra.sq >> Rb_or_imm<5:0>; }});
+
+ 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }});
+ 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }});
+ 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }});
+ 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }});
+
+ 0x52: mskwh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra;
+ }});
+ 0x62: msklh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra;
+ }});
+ 0x72: mskqh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra;
+ }});
+
+ 0x06: extbl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }});
+ 0x16: extwl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<15:0>; }});
+ 0x26: extll({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<31:0>; }});
+ 0x36: extql({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8)); }});
+
+ 0x5a: extwh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }});
+ 0x6a: extlh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }});
+ 0x7a: extqh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }});
+
+ 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }});
+
+ 0x57: inswh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq<15:0> >> (64 - 8 * bv)) : 0;
+ }});
+ 0x67: inslh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq<31:0> >> (64 - 8 * bv)) : 0;
+ }});
+ 0x77: insqh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq >> (64 - 8 * bv)) : 0;
+ }});
+
+ 0x30: zap({{
+ uint64_t zapmask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (Rb_or_imm<i:>)
+ zapmask |= (mask(8) << (i * 8));
+ }
+ Rc = Ra & ~zapmask;
+ }});
+ 0x31: zapnot({{
+ uint64_t zapmask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (!Rb_or_imm<i:>)
+ zapmask |= (mask(8) << (i * 8));
+ }
+ Rc = Ra & ~zapmask;
+ }});
+ }
+
+ 0x13: decode INTFUNC { // integer multiplies
+ 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
+ 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
+ 0x30: umulh({{
+ uint64_t hi, lo;
+ mul128(Ra, Rb_or_imm, hi, lo);
+ Rc = hi;
+ }}, IntMultOp);
+ 0x40: mullv({{
+ // 32-bit multiply with trap on overflow
+ int64_t Rax = Ra.sl; // sign extended version of Ra.sl
+ int64_t Rbx = Rb_or_imm.sl;
+ int64_t tmp = Rax * Rbx;
+ // To avoid overflow, all the upper 32 bits must match
+ // the sign bit of the lower 32. We code this as
+ // 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 = IntegerOverflowFault;
+ Rc.sl = tmp<31:0>;
+ }}, IntMultOp);
+ 0x60: mulqv({{
+ // 64-bit multiply with trap on overflow
+ uint64_t hi, lo;
+ mul128(Ra, Rb_or_imm, hi, lo);
+ // all the upper 64 bits must match the sign bit of
+ // the lower 64
+ if (!((hi == 0 && lo<63:> == 0) ||
+ (hi == mask(64) && lo<63:> == 1)))
+ fault = IntegerOverflowFault;
+ Rc = lo;
+ }}, IntMultOp);
+ }
+
+ 0x1c: decode INTFUNC {
+ 0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
+ 0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
+ 0x32: ctlz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (temp<63:32>) temp >>= 32; else count += 32;
+ if (temp<31:16>) temp >>= 16; else count += 16;
+ if (temp<15:8>) temp >>= 8; else count += 8;
+ if (temp<7:4>) temp >>= 4; else count += 4;
+ if (temp<3:2>) temp >>= 2; else count += 2;
+ if (temp<1:1>) temp >>= 1; else count += 1;
+ if ((temp<0:0>) != 0x1) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ 0x33: cttz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (!(temp<31:0>)) { temp >>= 32; count += 32; }
+ if (!(temp<15:0>)) { temp >>= 16; count += 16; }
+ if (!(temp<7:0>)) { temp >>= 8; count += 8; }
+ if (!(temp<3:0>)) { temp >>= 4; count += 4; }
+ if (!(temp<1:0>)) { temp >>= 2; count += 2; }
+ if (!(temp<0:0> & ULL(0x1))) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ format FailUnimpl {
+ 0x30: ctpop();
+ 0x31: perr();
+ 0x34: unpkbw();
+ 0x35: unpkbl();
+ 0x36: pkwb();
+ 0x37: pklb();
+ 0x38: minsb8();
+ 0x39: minsw4();
+ 0x3a: minub8();
+ 0x3b: minuw4();
+ 0x3c: maxub8();
+ 0x3d: maxuw4();
+ 0x3e: maxsb8();
+ 0x3f: maxsw4();
+ }
+
+ format BasicOperateWithNopCheck {
+ 0x70: decode RB {
+ 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
+ }
+ 0x78: decode RB {
+ 31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
+ FloatCvtOp);
+ }
+ }
+ }
+ }
+
+ // Conditional branches.
+ format CondBranch {
+ 0x39: beq({{ cond = (Ra == 0); }});
+ 0x3d: bne({{ cond = (Ra != 0); }});
+ 0x3e: bge({{ cond = (Ra.sq >= 0); }});
+ 0x3f: bgt({{ cond = (Ra.sq > 0); }});
+ 0x3b: ble({{ cond = (Ra.sq <= 0); }});
+ 0x3a: blt({{ cond = (Ra.sq < 0); }});
+ 0x38: blbc({{ cond = ((Ra & 1) == 0); }});
+ 0x3c: blbs({{ cond = ((Ra & 1) == 1); }});
+
+ 0x31: fbeq({{ cond = (Fa == 0); }});
+ 0x35: fbne({{ cond = (Fa != 0); }});
+ 0x36: fbge({{ cond = (Fa >= 0); }});
+ 0x37: fbgt({{ cond = (Fa > 0); }});
+ 0x33: fble({{ cond = (Fa <= 0); }});
+ 0x32: fblt({{ cond = (Fa < 0); }});
+ }
+
+ // unconditional branches
+ format UncondBranch {
+ 0x30: br();
+ 0x34: bsr(IsCall);
+ }
+
+ // indirect branches
+ 0x1a: decode JMPFUNC {
+ format Jump {
+ 0: jmp();
+ 1: jsr(IsCall);
+ 2: ret(IsReturn);
+ 3: jsr_coroutine(IsCall, IsReturn);
+ }
+ }
+
+ // Square root and integer-to-FP moves
+ 0x14: decode FP_SHORTFUNC {
+ // Integer to FP register moves must have RB == 31
+ 0x4: decode RB {
+ 31: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
+ 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
+ 0x014: FailUnimpl::itoff(); // VAX-format conversion
+ }
+ }
+ }
+
+ // Square root instructions must have FA == 31
+ 0xb: decode FA {
+ 31: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+#if SS_COMPATIBLE_FP
+ 0x0b: sqrts({{
+ if (Fb < 0.0)
+ fault = ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+#else
+ 0x0b: sqrts({{
+ if (Fb.sf < 0.0)
+ fault = ArithmeticFault;
+ Fc.sf = sqrt(Fb.sf);
+ }}, FloatSqrtOp);
+#endif
+ 0x2b: sqrtt({{
+ if (Fb < 0.0)
+ fault = ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+ }
+ }
+ }
+
+ // VAX-format sqrtf and sqrtg are not implemented
+ 0xa: FailUnimpl::sqrtfg();
+ }
+
+ // IEEE floating point
+ 0x16: decode FP_SHORTFUNC_TOP2 {
+ // The top two bits of the short function code break this
+ // space into four groups: binary ops, compares, reserved, and
+ // conversions. See Table 4-12 of AHB. There are different
+ // special cases in these different groups, so we decode on
+ // these top two bits first just to select a decode strategy.
+ // Most of these instructions may have various trapping and
+ // rounding mode flags set; these are decoded in the
+ // FloatingPointDecode template used by the
+ // FloatingPointOperate format.
+
+ // add/sub/mul/div: just decode on the short function code
+ // and source type. All valid trapping and rounding modes apply.
+ 0: decode FP_TRAPMODE {
+ // check for valid trapping modes here
+ 0,1,5,7: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+#if SS_COMPATIBLE_FP
+ 0x00: adds({{ Fc = Fa + Fb; }});
+ 0x01: subs({{ Fc = Fa - Fb; }});
+ 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
+#else
+ 0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
+ 0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
+ 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
+ 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
+#endif
+
+ 0x20: addt({{ Fc = Fa + Fb; }});
+ 0x21: subt({{ Fc = Fa - Fb; }});
+ 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
+ }
+ }
+ }
+
+ // Floating-point compare instructions must have the default
+ // rounding mode, and may use the default trapping mode or
+ // /SU. Both trapping modes are treated the same by M5; the
+ // only difference on the real hardware (as far a I can tell)
+ // is that without /SU you'd get an imprecise trap if you
+ // tried to compare a NaN with something else (instead of an
+ // "unordered" result).
+ 1: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a4, 0x5a4: cmptun({{ // unordered
+ Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
+ }}, FloatCmpOp);
+ }
+ }
+
+ // The FP-to-integer and integer-to-FP conversion insts
+ // require that FA be 31.
+ 3: decode FA {
+ 31: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+ 0x2f: decode FP_ROUNDMODE {
+ format FPFixedRounding {
+ // "chopped" i.e. round toward zero
+ 0: cvttq({{ Fc.sq = (int64_t)trunc(Fb); }},
+ Chopped);
+ // round to minus infinity
+ 1: cvttq({{ Fc.sq = (int64_t)floor(Fb); }},
+ MinusInfinity);
+ }
+ default: cvttq({{ Fc.sq = (int64_t)nearbyint(Fb); }});
+ }
+
+ // The cvtts opcode is overloaded to be cvtst if the trap
+ // mode is 2 or 6 (which are not valid otherwise)
+ 0x2c: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ // trap on denorm version "cvtst/s" is
+ // simulated same as cvtst
+ 0x2ac, 0x6ac: cvtst({{ Fc = Fb.sf; }});
+ }
+ default: cvtts({{ Fc.sf = Fb; }});
+ }
+
+ // The trapping mode for integer-to-FP conversions
+ // must be /SUI or nothing; /U and /SU are not
+ // allowed. The full set of rounding modes are
+ // supported though.
+ 0x3c: decode FP_TRAPMODE {
+ 0,7: cvtqs({{ Fc.sf = Fb.sq; }});
+ }
+ 0x3e: decode FP_TRAPMODE {
+ 0,7: cvtqt({{ Fc = Fb.sq; }});
+ }
+ }
+ }
+ }
+ }
+
+ // misc FP operate
+ 0x17: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x010: cvtlq({{
+ Fc.sl = (Fb.uq<63:62> << 30) | Fb.uq<58:29>;
+ }});
+ 0x030: cvtql({{
+ Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
+ }});
+
+ // We treat the precise & imprecise trapping versions of
+ // cvtql identically.
+ 0x130, 0x530: cvtqlv({{
+ // To avoid overflow, all the upper 32 bits must match
+ // the sign bit of the lower 32. We code this as
+ // 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 = IntegerOverflowFault;
+ Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
+ }});
+
+ 0x020: cpys({{ // copy sign
+ Fc.uq = (Fa.uq<63:> << 63) | Fb.uq<62:0>;
+ }});
+ 0x021: cpysn({{ // copy sign negated
+ Fc.uq = (~Fa.uq<63:> << 63) | Fb.uq<62:0>;
+ }});
+ 0x022: cpyse({{ // copy sign and exponent
+ Fc.uq = (Fa.uq<63:52> << 52) | Fb.uq<51:0>;
+ }});
+
+ 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }});
+ 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }});
+ 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }});
+ 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }});
+ 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }});
+ 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }});
+
+ 0x024: mt_fpcr({{ FPCR = Fa.uq; }});
+ 0x025: mf_fpcr({{ Fa.uq = FPCR; }});
+ }
+ }
+
+ // miscellaneous mem-format ops
+ 0x18: decode MEMFUNC {
+ format WarnUnimpl {
+ 0x8000: fetch();
+ 0xa000: fetch_m();
+ 0xe800: ecb();
+ }
+
+ format MiscPrefetch {
+ 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
+ {{ xc->writeHint(EA, 64, memAccessFlags); }},
+ mem_flags = NO_FAULT,
+ inst_flags = [IsMemRef, IsDataPrefetch,
+ IsStore, MemWriteOp]);
+ }
+
+ format BasicOperate {
+ 0xc000: rpcc({{
+#if FULL_SYSTEM
+ /* Rb is a fake dependency so here is a fun way to get
+ * the parser to understand that.
+ */
+ Ra = xc->readIpr(AlphaISA::IPR_CC, fault) + (Rb & 0);
+
+#else
+ Ra = curTick;
+#endif
+ }});
+
+ // All of the barrier instructions below do nothing in
+ // their execute() methods (hence the empty code blocks).
+ // All of their functionality is hard-coded in the
+ // pipeline based on the flags IsSerializing,
+ // IsMemBarrier, and IsWriteBarrier. In the current
+ // detailed CPU model, the execute() function only gets
+ // called at fetch, so there's no way to generate pipeline
+ // behavior at any other stage. Once we go to an
+ // exec-in-exec CPU model we should be able to get rid of
+ // these flags and implement this behavior via the
+ // execute() methods.
+
+ // trapb is just a barrier on integer traps, where excb is
+ // a barrier on integer and FP traps. "EXCB is thus a
+ // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
+ // them the same though.
+ 0x0000: trapb({{ }}, IsSerializing, No_OpClass);
+ 0x0400: excb({{ }}, IsSerializing, No_OpClass);
+ 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
+ 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
+ }
+
+#if FULL_SYSTEM
+ format BasicOperate {
+ 0xe000: rc({{
+ Ra = xc->readIntrFlag();
+ xc->setIntrFlag(0);
+ }}, IsNonSpeculative);
+ 0xf000: rs({{
+ Ra = xc->readIntrFlag();
+ xc->setIntrFlag(1);
+ }}, IsNonSpeculative);
+ }
+#else
+ format FailUnimpl {
+ 0xe000: rc();
+ 0xf000: rs();
+ }
+#endif
+ }
+
+#if FULL_SYSTEM
+ 0x00: CallPal::call_pal({{
+ if (!palValid ||
+ (palPriv
+ && 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 = UnimplementedOpcodeFault;
+ }
+ else {
+ // check to see if simulator wants to do something special
+ // on this PAL call (including maybe suppress it)
+ bool dopal = xc->simPalCheck(palFunc);
+
+ if (dopal) {
+ AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
+ xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
+ NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
+ }
+ }
+ }}, IsNonSpeculative);
+#else
+ 0x00: decode PALFUNC {
+ format EmulatedCallPal {
+ 0x00: halt ({{
+ SimExit(curTick, "halt instruction encountered");
+ }}, IsNonSpeculative);
+ 0x83: callsys({{
+ xc->syscall();
+ }}, IsNonSpeculative);
+ // Read uniq reg into ABI return value register (r0)
+ 0x9e: rduniq({{ R0 = Runiq; }});
+ // Write uniq reg with value from ABI arg register (r16)
+ 0x9f: wruniq({{ Runiq = R16; }});
+ }
+ }
+#endif
+
+#if FULL_SYSTEM
+ format HwLoad {
+ 0x1b: decode HW_LDST_QUAD {
+ 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
+ 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
+ }
+ }
+
+ format HwStore {
+ 0x1f: decode HW_LDST_COND {
+ 0: decode HW_LDST_QUAD {
+ 0: hw_st({{ EA = (Rb + disp) & ~3; }},
+ {{ Mem.ul = Ra<31:0>; }}, L);
+ 1: hw_st({{ EA = (Rb + disp) & ~7; }},
+ {{ Mem.uq = Ra.uq; }}, Q);
+ }
+
+ 1: FailUnimpl::hw_st_cond();
+ }
+ }
+
+ format HwMoveIPR {
+ 0x19: hw_mfpr({{
+ // this instruction is only valid in PAL mode
+ if (!xc->inPalMode()) {
+ fault = UnimplementedOpcodeFault;
+ }
+ else {
+ Ra = xc->readIpr(ipr_index, fault);
+ }
+ }});
+ 0x1d: hw_mtpr({{
+ // this instruction is only valid in PAL mode
+ if (!xc->inPalMode()) {
+ fault = UnimplementedOpcodeFault;
+ }
+ else {
+ xc->setIpr(ipr_index, Ra);
+ if (traceData) { traceData->setData(Ra); }
+ }
+ }});
+ }
+
+ format BasicOperate {
+ 0x1e: hw_rei({{ xc->hwrei(); }}, IsSerializing);
+
+ // M5 special opcodes use the reserved 0x01 opcode space
+ 0x01: decode M5FUNC {
+ 0x00: arm({{
+ AlphaPseudo::arm(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x01: quiesce({{
+ AlphaPseudo::quiesce(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x10: ivlb({{
+ AlphaPseudo::ivlb(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x11: ivle({{
+ AlphaPseudo::ivle(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x20: m5exit_old({{
+ AlphaPseudo::m5exit_old(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x21: m5exit({{
+ AlphaPseudo::m5exit(xc->xcBase(), R16);
+ }}, No_OpClass, IsNonSpeculative);
+ 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
+ 0x40: resetstats({{
+ AlphaPseudo::resetstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x41: dumpstats({{
+ AlphaPseudo::dumpstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x42: dumpresetstats({{
+ AlphaPseudo::dumpresetstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x43: m5checkpoint({{
+ AlphaPseudo::m5checkpoint(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x50: m5readfile({{
+ R0 = AlphaPseudo::readfile(xc->xcBase(), R16, R17, R18);
+ }}, IsNonSpeculative);
+ 0x51: m5break({{
+ AlphaPseudo::debugbreak(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x52: m5switchcpu({{
+ AlphaPseudo::switchcpu(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x53: m5addsymbol({{
+ AlphaPseudo::addsymbol(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+
+ }
+ }
+#endif
+}
diff --git a/arch/alpha/isa/fp.isa b/arch/alpha/isa/fp.isa
new file mode 100644
index 000000000..c718c5524
--- /dev/null
+++ b/arch/alpha/isa/fp.isa
@@ -0,0 +1,300 @@
+// -*- 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 exec {{
+ /// Check "FP enabled" machine status bit. Called when executing any FP
+ /// instruction in full-system mode.
+ /// @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 = NoFault; // dummy... this ipr access should not fault
+ if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
+ fault = FloatEnableFault;
+ }
+ return fault;
+ }
+#else
+ inline Fault * checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#endif
+}};
+
+output header {{
+ /**
+ * Base class for general floating-point instructions. Includes
+ * support for various Alpha rounding and trapping modes. Only FP
+ * instructions that require this support are derived from this
+ * class; the rest derive directly from AlphaStaticInst.
+ */
+ class AlphaFP : public AlphaStaticInst
+ {
+ public:
+ /// Alpha FP rounding modes.
+ enum RoundingMode {
+ Chopped = 0, ///< round toward zero
+ Minus_Infinity = 1, ///< round toward minus infinity
+ Normal = 2, ///< round to nearest (default)
+ Dynamic = 3, ///< use FPCR setting (in instruction)
+ Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
+ };
+
+ /// Alpha FP trapping modes.
+ /// For instructions that produce integer results, the
+ /// "Underflow Enable" modes really mean "Overflow Enable", and
+ /// the assembly modifier is V rather than U.
+ enum TrappingMode {
+ /// default: nothing enabled
+ Imprecise = 0, ///< no modifier
+ /// underflow/overflow traps enabled, inexact disabled
+ Underflow_Imprecise = 1, ///< /U or /V
+ Underflow_Precise = 5, ///< /SU or /SV
+ /// underflow/overflow and inexact traps enabled
+ Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
+ };
+
+ protected:
+ /// Map Alpha rounding mode to C99 constants from <fenv.h>.
+ static const int alphaToC99RoundingMode[];
+
+ /// Map enum RoundingMode values to disassembly suffixes.
+ static const char *roundingModeSuffix[];
+ /// Map enum TrappingMode values to FP disassembly suffixes.
+ static const char *fpTrappingModeSuffix[];
+ /// Map enum TrappingMode values to integer disassembly suffixes.
+ static const char *intTrappingModeSuffix[];
+
+ /// This instruction's rounding mode.
+ RoundingMode roundingMode;
+ /// This instruction's trapping mode.
+ TrappingMode trappingMode;
+
+ /// Have we warned about this instruction's unsupported
+ /// rounding mode (if applicable)?
+ mutable bool warnedOnRounding;
+
+ /// Have we warned about this instruction's unsupported
+ /// trapping mode (if applicable)?
+ mutable bool warnedOnTrapping;
+
+ /// Constructor
+ AlphaFP(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ roundingMode((enum RoundingMode)FP_ROUNDMODE),
+ trappingMode((enum TrappingMode)FP_TRAPMODE),
+ warnedOnRounding(false),
+ warnedOnTrapping(false)
+ {
+ }
+
+ int getC99RoundingMode(uint64_t fpcr_val) const;
+
+ // This differs from the AlphaStaticInst version only in
+ // printing suffixes for non-default rounding & trapping modes.
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+
+output decoder {{
+ int
+ AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
+ {
+ if (roundingMode == Dynamic) {
+ return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
+ }
+ else {
+ return alphaToC99RoundingMode[roundingMode];
+ }
+ }
+
+ std::string
+ AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::string mnem_str(mnemonic);
+
+#ifndef SS_COMPATIBLE_DISASSEMBLY
+ std::string suffix("");
+ suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
+ ? fpTrappingModeSuffix[trappingMode]
+ : intTrappingModeSuffix[trappingMode]);
+ suffix += roundingModeSuffix[roundingMode];
+
+ if (suffix != "") {
+ mnem_str = csprintf("%s/%s", mnemonic, suffix);
+ }
+#endif
+
+ std::stringstream ss;
+ ccprintf(ss, "%-10s ", mnem_str.c_str());
+
+ // 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();
+ }
+
+ const int AlphaFP::alphaToC99RoundingMode[] = {
+ FE_TOWARDZERO, // Chopped
+ FE_DOWNWARD, // Minus_Infinity
+ FE_TONEAREST, // Normal
+ FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
+ };
+
+ const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
+ // mark invalid trapping modes, but don't fail on them, because
+ // you could decode anything on a misspeculated path
+ const char *AlphaFP::fpTrappingModeSuffix[] =
+ { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
+ const char *AlphaFP::intTrappingModeSuffix[] =
+ { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
+}};
+
+// FP instruction class execute method template. Handles non-standard
+// rounding modes.
+def template FloatingPointExecute {{
+ Fault * %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (trappingMode != Imprecise && !warnedOnTrapping) {
+ warn("%s: non-standard trapping mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnTrapping = true;
+ }
+
+ Fault * fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+#if USE_FENV
+ if (roundingMode == Normal) {
+ %(code)s;
+ } else {
+ fesetround(getC99RoundingMode(xc->readFpcr()));
+ %(code)s;
+ fesetround(FE_TONEAREST);
+ }
+#else
+ if (roundingMode != Normal && !warnedOnRounding) {
+ warn("%s: non-standard rounding mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnRounding = true;
+ }
+ %(code)s;
+#endif
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// FP instruction class execute method template where no dynamic
+// rounding mode control is needed. Like BasicExecute, but includes
+// check & warning for non-standard trapping mode.
+def template FPFixedRoundingExecute {{
+ Fault * %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (trappingMode != Imprecise && !warnedOnTrapping) {
+ warn("%s: non-standard trapping mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnTrapping = true;
+ }
+
+ Fault * fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template FloatingPointDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (FC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// General format for floating-point operate instructions:
+// - Checks trapping and rounding mode flags. Trapping modes
+// currently unimplemented (will fail).
+// - Generates NOP if FC == 31.
+def format FloatingPointOperate(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode_block = FloatingPointDecode.subst(iop)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FloatingPointExecute.subst(iop)
+}};
+
+// Special format for cvttq where rounding mode is pre-decoded
+def format FPFixedRounding(code, class_suffix, *opt_args) {{
+ Name += class_suffix
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode_block = FloatingPointDecode.subst(iop)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FPFixedRoundingExecute.subst(iop)
+}};
+
diff --git a/arch/alpha/isa/int.isa b/arch/alpha/isa/int.isa
new file mode 100644
index 000000000..049437f8c
--- /dev/null
+++ b/arch/alpha/isa/int.isa
@@ -0,0 +1,128 @@
+// -*- 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 {{
+ /**
+ * Base class for integer immediate instructions.
+ */
+ class IntegerImm : public AlphaStaticInst
+ {
+ protected:
+ /// Immediate operand value (unsigned 8-bit int).
+ uint8_t imm;
+
+ /// Constructor
+ IntegerImm(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first source reg... if there's
+ // a second one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+
+ ss << (int)imm;
+
+ if (_numDestRegs > 0) {
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+}};
+
+
+def template RegOrImmDecode {{
+ {
+ AlphaStaticInst *i =
+ (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
+ : (AlphaStaticInst *)new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// Primary format for integer operate instructions:
+// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
+// - Generates NOP if RC == 31.
+def format IntegerOperate(code, *opt_flags) {{
+ # If the code block contains 'Rb_or_imm', we define two instructions,
+ # one using 'Rb' and one using 'imm', and have the decoder select
+ # the right one.
+ uses_imm = (code.find('Rb_or_imm') != -1)
+ if uses_imm:
+ orig_code = code
+ # base code is reg version:
+ # rewrite by substituting 'Rb' for 'Rb_or_imm'
+ code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
+ # generate immediate version by substituting 'imm'
+ # note that imm takes no extenstion, so we extend
+ # the regexp to replace any extension as well
+ imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code)
+
+ # generate declaration for register version
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+
+ if uses_imm:
+ # append declaration for imm version
+ imm_cblk = CodeBlock(imm_code)
+ imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
+ opt_flags)
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += BasicExecute.subst(imm_iop)
+ # decode checks IMM bit to pick correct version
+ decode_block = RegOrImmDecode.subst(iop)
+ else:
+ # no imm version: just check for nop
+ decode_block = OperateNopCheckDecode.subst(iop)
+}};
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
new file mode 100644
index 000000000..42fb29404
--- /dev/null
+++ b/arch/alpha/isa/main.isa
@@ -0,0 +1,435 @@
+// -*- 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 {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#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
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/fenv.hh"
+#include "base/loader/symtab.hh"
+#include "config/ss_compatible_fp.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
+#include <math.h>
+}};
+
+output exec {{
+#include <math.h>
+
+#if FULL_SYSTEM
+#include "sim/pseudo_inst.hh"
+#endif
+#include "base/fenv.hh"
+#include "config/ss_compatible_fp.hh"
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// AlphaISAInst namespace.
+//
+
+
+namespace AlphaISA;
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Universal (format-independent) fields
+def bitfield OPCODE <31:26>;
+def bitfield RA <25:21>;
+def bitfield RB <20:16>;
+
+// Memory format
+def signed bitfield MEMDISP <15: 0>; // displacement
+def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned)
+
+// Memory-format jumps
+def bitfield JMPFUNC <15:14>; // function code (disp<15:14>)
+def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>)
+
+// Branch format
+def signed bitfield BRDISP <20: 0>; // displacement
+
+// Integer operate format(s>;
+def bitfield INTIMM <20:13>; // integer immediate (literal)
+def bitfield IMM <12:12>; // immediate flag
+def bitfield INTFUNC <11: 5>; // function code
+def bitfield RC < 4: 0>; // dest reg
+
+// Floating-point operate format
+def bitfield FA <25:21>;
+def bitfield FB <20:16>;
+def bitfield FP_FULLFUNC <15: 5>; // complete function code
+ def bitfield FP_TRAPMODE <15:13>; // trapping mode
+ def bitfield FP_ROUNDMODE <12:11>; // rounding mode
+ def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding
+ def bitfield FP_SRCTYPE <10: 9>; // source reg type
+ def bitfield FP_SHORTFUNC < 8: 5>; // short function code
+ def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code
+def bitfield FC < 4: 0>; // dest reg
+
+// PALcode format
+def bitfield PALFUNC <25: 0>; // function code
+
+// EV5 PAL instructions:
+// HW_LD/HW_ST
+def bitfield HW_LDST_PHYS <15>; // address is physical
+def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR
+def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc
+def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b
+def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch
+def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked
+def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional
+def signed bitfield HW_LDST_DISP <9:0>; // signed displacement
+
+// HW_REI
+def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk
+def bitfield HW_REI_MBZ <13: 0>; // must be zero
+
+// HW_MTPR/MW_MFPR
+def bitfield HW_IPR_IDX <15:0>; // IPR index
+
+// M5 instructions
+def bitfield M5FUNC <7:0>;
+
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sw' : ('signed int', 16),
+ 'uw' : ('unsigned int', 16),
+ 'sl' : ('signed int', 32),
+ 'ul' : ('unsigned int', 32),
+ 'sq' : ('signed int', 64),
+ 'uq' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64)
+}};
+
+def operands {{
+ # Int regs default to unsigned, but code should not count on this.
+ # For clarity, descriptions that depend on unsigned behavior should
+ # explicitly specify '.uq'.
+ 'Ra': ('IntReg', 'uq', 'RA', 'IsInteger', 1),
+ 'Rb': ('IntReg', 'uq', 'RB', 'IsInteger', 2),
+ 'Rc': ('IntReg', 'uq', 'RC', 'IsInteger', 3),
+ 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
+ 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
+ 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
+ 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ 'NPC': ('NPC', 'uq', 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),
+ 'R17': ('IntReg', 'uq', '17', None, 1),
+ 'R18': ('IntReg', 'uq', '18', None, 1)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Basic instruction classes/templates/formats etc.
+//
+
+output header {{
+// uncomment the following to get SimpleScalar-compatible disassembly
+// (useful for diffing output traces).
+// #define SS_COMPATIBLE_DISASSEMBLY
+
+ /**
+ * Base class for all Alpha static instructions.
+ */
+ class AlphaStaticInst : public StaticInst<AlphaISA>
+ {
+ protected:
+
+ /// Make AlphaISA register dependence tags directly visible in
+ /// this class and derived classes. Maybe these should really
+ /// live here and not in the AlphaISA namespace.
+ enum DependenceTags {
+ FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
+ Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
+ Uniq_DepTag = AlphaISA::Uniq_DepTag,
+ IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
+ };
+
+ /// Constructor.
+ AlphaStaticInst(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : StaticInst<AlphaISA>(mnem, _machInst, __opClass)
+ {
+ }
+
+ /// Print a register name for disassembly given the unique
+ /// dependence tag number (FP or int).
+ void printReg(std::ostream &os, int reg) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ void
+ AlphaStaticInst::printReg(std::ostream &os, int reg) const
+ {
+ if (reg < FP_Base_DepTag) {
+ ccprintf(os, "r%d", reg);
+ }
+ else {
+ ccprintf(os, "f%d", reg - FP_Base_DepTag);
+ }
+ }
+
+ std::string
+ AlphaStaticInst::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();
+ }
+}};
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault * execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ /// Constructor.
+ %(class_name)s(MachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault * %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault * fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// The most basic instruction format... used only for a few misc. insts
+def format BasicOperate(code, *flags) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
+
+output header {{
+ /**
+ * Static instruction class for no-ops. This is a leaf class.
+ */
+ class Nop : public AlphaStaticInst
+ {
+ /// Disassembly of original instruction.
+ const std::string originalDisassembly;
+
+ public:
+ /// Constructor
+ Nop(const std::string _originalDisassembly, MachInst _machInst)
+ : AlphaStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ flags[IsNop] = true;
+ }
+
+ ~Nop() { }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+output decoder {{
+ 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
+ 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 NoFault;
+ }
+}};
+
+// integer & FP operate instructions use Rc as dest, so check for
+// Rc == 31 to detect nops
+def template OperateNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// Like BasicOperate format, but generates NOP if RC/FC == 31
+def format BasicOperateWithNopCheck(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
+ opt_args)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+// Integer instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/int.isa"
+
+// Floating-point instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/fp.isa"
+
+// Memory instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/mem.isa"
+
+// Branch/jump instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/branch.isa"
+
+// PAL instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/pal.isa"
+
+// Unimplemented instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/unimp.isa"
+
+// Unknown instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/unknown.isa"
+
+// Execution utility functions
+##include "m5/arch/alpha/isa/util.isa"
+
+// The actual decoder
+##include "m5/arch/alpha/isa/decoder.isa"
diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa
new file mode 100644
index 000000000..df26a534d
--- /dev/null
+++ b/arch/alpha/isa/mem.isa
@@ -0,0 +1,702 @@
+// -*- 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 {{
+ /**
+ * Base class for general Alpha memory-format instructions.
+ */
+ class Memory : public AlphaStaticInst
+ {
+ protected:
+
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr<AlphaISA> eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr<AlphaISA> memAccPtr;
+
+ /// Constructor
+ Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
+ };
+
+ /**
+ * Base class for memory-format instructions using a 32-bit
+ * displacement (i.e. most of them).
+ */
+ class MemoryDisp32 : public Memory
+ {
+ protected:
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+
+ /// Constructor.
+ MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(MEMDISP)
+ {
+ }
+ };
+
+
+ /**
+ * Base class for a few miscellaneous memory-format insts
+ * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
+ * None of these instructions has a destination register either.
+ */
+ class MemoryNoDisp : public Memory
+ {
+ protected:
+ /// Constructor
+ MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+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);
+ }
+
+ std::string
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (r%d)", mnemonic, 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:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ EAComp(MachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ /**
+ * "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
+ };
+}};
+
+
+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 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;
+ }
+}};
+
+
+def template MiscMemAccExecute {{
+ 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) {
+ %(code)s;
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscExecute {{
+ 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) {
+ %(memacc_code)s;
+ }
+
+ 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;
+ }
+}};
+
+// load instructions use Ra as dest, so check for
+// Ra == 31 to detect nops
+def template LoadNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RA == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+
+// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
+def template LoadPrefetchCheckDecode {{
+ {
+ if (RA != 31) {
+ return new %(class_name)s(machInst);
+ }
+ else {
+ return new %(class_name)sPrefetch(machInst);
+ }
+ }
+}};
+
+
+let {{
+def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code = '', base_class = 'MemoryDisp32',
+ 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))
+}};
+
+
+def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + 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')
+}};
+
+
+// Note that the flags passed in apply only to the prefetch version
+def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], pf_flags = [], inst_flags = []) {{
+ # declare the load instruction object and generate the decode block
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadPrefetchCheckDecode,
+ exec_template_base = 'Load')
+
+ # Declare the prefetch instruction object.
+
+ # Make sure flag args are lists so we can mess with them.
+ mem_flags = makeList(mem_flags)
+ pf_flags = makeList(pf_flags)
+ inst_flags = makeList(inst_flags)
+
+ pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
+ pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
+ 'IsDataPrefetch', 'MemReadOp']
+
+ (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
+ LoadStoreBase(name, Name + 'Prefetch', ea_code,
+ 'xc->prefetch(EA, memAccessFlags);',
+ pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
+
+ header_output += pf_header_output
+ decoder_output += pf_decoder_output
+ exec_output += pf_exec_output
+}};
+
+
+def format Store(memacc_code, ea_code = {{ EA = Rb + 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')
+}};
+
+
+def format StoreCond(memacc_code, postacc_code,
+ ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code, exec_template_base = 'Store')
+}};
+
+
+// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
+def format MiscPrefetch(ea_code, 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,
+ base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
+}};
+
+
diff --git a/arch/alpha/isa/pal.isa b/arch/alpha/isa/pal.isa
new file mode 100644
index 000000000..b68a7c19f
--- /dev/null
+++ b/arch/alpha/isa/pal.isa
@@ -0,0 +1,271 @@
+// -*- 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 {{
+ /**
+ * Base class for emulated call_pal calls (used only in
+ * non-full-system mode).
+ */
+ class EmulatedCallPal : public AlphaStaticInst
+ {
+ protected:
+
+ /// Constructor.
+ EmulatedCallPal(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ EmulatedCallPal::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%s %s", "call_pal", mnemonic);
+#else
+ return csprintf("%-10s %s", "call_pal", mnemonic);
+#endif
+ }
+}};
+
+def format EmulatedCallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+output header {{
+ /**
+ * Base class for full-system-mode call_pal instructions.
+ * Probably could turn this into a leaf class and get rid of the
+ * parser template.
+ */
+ class CallPalBase : public AlphaStaticInst
+ {
+ protected:
+ int palFunc; ///< Function code part of instruction
+ int palOffset; ///< Target PC, offset from IPR_PAL_BASE
+ bool palValid; ///< is the function code valid?
+ bool palPriv; ///< is this call privileged?
+
+ /// Constructor.
+ CallPalBase(const char *mnem, MachInst _machInst,
+ OpClass __opClass);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ inline
+ CallPalBase::CallPalBase(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ palFunc(PALFUNC)
+ {
+ // From the 21164 HRM (paraphrased):
+ // Bit 7 of the function code (mask 0x80) indicates
+ // whether the call is privileged (bit 7 == 0) or
+ // unprivileged (bit 7 == 1). The privileged call table
+ // starts at 0x2000, the unprivielged call table starts at
+ // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
+ // offset.
+ const int palPrivMask = 0x80;
+ const int palOffsetMask = 0x3f;
+
+ // Pal call is invalid unless all other bits are 0
+ palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+ palPriv = ((machInst & palPrivMask) == 0);
+ int shortPalFunc = (machInst & palOffsetMask);
+ // Add 1 to base to set pal-mode bit
+ palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
+ }
+
+ std::string
+ CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %#x", "call_pal", palFunc);
+ }
+}};
+
+def format CallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// hw_ld, hw_st
+//
+
+output header {{
+ /**
+ * Base class for hw_ld and hw_st.
+ */
+ class HwLoadStore : public Memory
+ {
+ protected:
+
+ /// Displacement for EA calculation (signed).
+ int16_t disp;
+
+ /// Constructor
+ HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ inline
+ HwLoadStore::HwLoadStore(const char *mnem, MachInst _machInst,
+ OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(HW_LDST_DISP)
+ {
+ memAccessFlags = 0;
+ if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
+ if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
+ if (HW_LDST_VPTE) memAccessFlags |= VPTE;
+ if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
+ }
+
+ std::string
+ HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
+#else
+ // HW_LDST_LOCK and HW_LDST_COND are the same bit.
+ const char *lock_str =
+ (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
+
+ return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
+ mnemonic, RA, disp, RB,
+ HW_LDST_PHYS ? ",PHYS" : "",
+ HW_LDST_ALT ? ",ALT" : "",
+ HW_LDST_QUAD ? ",QUAD" : "",
+ HW_LDST_VPTE ? ",VPTE" : "",
+ lock_str);
+#endif
+ }
+}};
+
+def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore', exec_template_base = 'Load')
+}};
+
+
+def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore', exec_template_base = 'Store')
+}};
+
+
+def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext,
+ *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ postacc_code, mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore')
+}};
+
+
+output header {{
+ /**
+ * Base class for hw_mfpr and hw_mtpr.
+ */
+ class HwMoveIPR : public AlphaStaticInst
+ {
+ protected:
+ /// Index of internal processor register.
+ int ipr_index;
+
+ /// Constructor
+ HwMoveIPR(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ ipr_index(HW_IPR_IDX)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ if (_numSrcRegs > 0) {
+ // must be mtpr
+ return csprintf("%-10s r%d,IPR(%#x)",
+ mnemonic, RA, ipr_index);
+ }
+ else {
+ // must be mfpr
+ return csprintf("%-10s IPR(%#x),r%d",
+ mnemonic, ipr_index, RA);
+ }
+ }
+}};
+
+def format HwMoveIPR(code) {{
+ iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
+ ['IprAccessOp'])
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
diff --git a/arch/alpha/isa/unimp.isa b/arch/alpha/isa/unimp.isa
new file mode 100644
index 000000000..ce8197708
--- /dev/null
+++ b/arch/alpha/isa/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 AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : AlphaStaticInst(_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 AlphaStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : AlphaStaticInst(_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 UnimplementedOpcodeFault;
+ }
+
+ Fault *
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
+
+ return NoFault;
+ }
+}};
+
+
+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 AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(MachInst _machInst)
+ : AlphaStaticInst("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/alpha/isa/unknown.isa b/arch/alpha/isa/unknown.isa
new file mode 100644
index 000000000..e7f8bc8db
--- /dev/null
+++ b/arch/alpha/isa/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 UnimplementedOpcodeFault;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
+
diff --git a/arch/alpha/isa/util.isa b/arch/alpha/isa/util.isa
new file mode 100644
index 000000000..9fbbf6636
--- /dev/null
+++ b/arch/alpha/isa/util.isa
@@ -0,0 +1,112 @@
+// -*- 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 exec {{
+
+ /// Return opa + opb, summing carry into third arg.
+ inline uint64_t
+ addc(uint64_t opa, uint64_t opb, int &carry)
+ {
+ uint64_t res = opa + opb;
+ if (res < opa || res < opb)
+ ++carry;
+ return res;
+ }
+
+ /// Multiply two 64-bit values (opa * opb), returning the 128-bit
+ /// product in res_hi and res_lo.
+ inline void
+ mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
+ {
+ // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
+ uint64_t opa_hi = opa<63:32>;
+ uint64_t opa_lo = opa<31:0>;
+ uint64_t opb_hi = opb<63:32>;
+ uint64_t opb_lo = opb<31:0>;
+
+ res_lo = opa_lo * opb_lo;
+
+ // The middle partial products logically belong in bit
+ // positions 95 to 32. Thus the lower 32 bits of each product
+ // sum into the upper 32 bits of the low result, while the
+ // upper 32 sum into the low 32 bits of the upper result.
+ uint64_t partial1 = opa_hi * opb_lo;
+ uint64_t partial2 = opa_lo * opb_hi;
+
+ uint64_t partial1_lo = partial1<31:0> << 32;
+ uint64_t partial1_hi = partial1<63:32>;
+ uint64_t partial2_lo = partial2<31:0> << 32;
+ uint64_t partial2_hi = partial2<63:32>;
+
+ // Add partial1_lo and partial2_lo to res_lo, keeping track
+ // of any carries out
+ int carry_out = 0;
+ res_lo = addc(partial1_lo, res_lo, carry_out);
+ res_lo = addc(partial2_lo, res_lo, carry_out);
+
+ // Now calculate the high 64 bits...
+ res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out;
+ }
+
+ /// Map 8-bit S-floating exponent to 11-bit T-floating exponent.
+ /// See Table 2-2 of Alpha AHB.
+ inline int
+ map_s(int old_exp)
+ {
+ int hibit = old_exp<7:>;
+ int lobits = old_exp<6:0>;
+
+ if (hibit == 1) {
+ return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits);
+ }
+ else {
+ return (lobits == 0) ? 0 : (0x380 | lobits);
+ }
+ }
+
+ /// Convert a 32-bit S-floating value to the equivalent 64-bit
+ /// representation to be stored in an FP reg.
+ inline uint64_t
+ s_to_t(uint32_t s_val)
+ {
+ uint64_t tmp = s_val;
+ return (tmp<31:> << 63 // sign bit
+ | (uint64_t)map_s(tmp<30:23>) << 52 // exponent
+ | tmp<22:0> << 29); // fraction
+ }
+
+ /// Convert a 64-bit T-floating value to the equivalent 32-bit
+ /// S-floating representation to be stored in memory.
+ inline int32_t
+ t_to_s(uint64_t t_val)
+ {
+ return (t_val<63:62> << 30 // sign bit & hi exp bit
+ | t_val<58:29>); // rest of exp & fraction
+ }
+}};
+
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
deleted file mode 100644
index c998b1a0a..000000000
--- a/arch/alpha/isa_desc
+++ /dev/null
@@ -1,2737 +0,0 @@
-// -*- mode:c++ -*-
-
-//Copyright (c) 2003, 2004, 2005
-//The Regents of The University of Michigan
-//All Rights Reserved
-
-//This code is part of the M5 simulator, developed by Nathan Binkert,
-//Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
-//from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi,
-//and Andrew Schultz.
-
-//Permission is granted to use, copy, create derivative works and
-//redistribute this software and such derivative works for any purpose,
-//so long as the copyright notice above, this grant of permission, and
-//the disclaimer below appear in all copies made; and so long as the
-//name of The University of Michigan is not used in any advertising or
-//publicity pertaining to the use or distribution of this software
-//without specific, written prior authorization.
-
-//THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
-//UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT
-//WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR
-//IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
-//MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF
-//THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
-//INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-//DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION
-//WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
-//ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-////////////////////////////////////////////////////////////////////
-//
-// Alpha ISA description file.
-//
-////////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Output include file directives.
-//
-
-output header {{
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-
-#include "config/ss_compatible_fp.hh"
-#include "cpu/static_inst.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
-}};
-
-output decoder {{
-#include "base/cprintf.hh"
-#include "base/fenv.hh"
-#include "base/loader/symtab.hh"
-#include "config/ss_compatible_fp.hh"
-#include "cpu/exec_context.hh" // for Jump::branchTarget()
-
-#include <math.h>
-}};
-
-output exec {{
-#include <math.h>
-
-#if FULL_SYSTEM
-#include "arch/alpha/pseudo_inst.hh"
-#endif
-#include "base/fenv.hh"
-#include "config/ss_compatible_fp.hh"
-#include "cpu/base.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Namespace statement. Everything below this line will be in the
-// AlphaISAInst namespace.
-//
-
-
-namespace AlphaISA;
-
-////////////////////////////////////////////////////////////////////
-//
-// Bitfield definitions.
-//
-
-// Universal (format-independent) fields
-def bitfield OPCODE <31:26>;
-def bitfield RA <25:21>;
-def bitfield RB <20:16>;
-
-// Memory format
-def signed bitfield MEMDISP <15: 0>; // displacement
-def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned)
-
-// Memory-format jumps
-def bitfield JMPFUNC <15:14>; // function code (disp<15:14>)
-def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>)
-
-// Branch format
-def signed bitfield BRDISP <20: 0>; // displacement
-
-// Integer operate format(s>;
-def bitfield INTIMM <20:13>; // integer immediate (literal)
-def bitfield IMM <12:12>; // immediate flag
-def bitfield INTFUNC <11: 5>; // function code
-def bitfield RC < 4: 0>; // dest reg
-
-// Floating-point operate format
-def bitfield FA <25:21>;
-def bitfield FB <20:16>;
-def bitfield FP_FULLFUNC <15: 5>; // complete function code
- def bitfield FP_TRAPMODE <15:13>; // trapping mode
- def bitfield FP_ROUNDMODE <12:11>; // rounding mode
- def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding
- def bitfield FP_SRCTYPE <10: 9>; // source reg type
- def bitfield FP_SHORTFUNC < 8: 5>; // short function code
- def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code
-def bitfield FC < 4: 0>; // dest reg
-
-// PALcode format
-def bitfield PALFUNC <25: 0>; // function code
-
-// EV5 PAL instructions:
-// HW_LD/HW_ST
-def bitfield HW_LDST_PHYS <15>; // address is physical
-def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR
-def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc
-def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b
-def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch
-def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked
-def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional
-def signed bitfield HW_LDST_DISP <9:0>; // signed displacement
-
-// HW_REI
-def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk
-def bitfield HW_REI_MBZ <13: 0>; // must be zero
-
-// HW_MTPR/MW_MFPR
-def bitfield HW_IPR_IDX <15:0>; // IPR index
-
-// M5 instructions
-def bitfield M5FUNC <7:0>;
-
-def operand_types {{
- 'sb' : ('signed int', 8),
- 'ub' : ('unsigned int', 8),
- 'sw' : ('signed int', 16),
- 'uw' : ('unsigned int', 16),
- 'sl' : ('signed int', 32),
- 'ul' : ('unsigned int', 32),
- 'sq' : ('signed int', 64),
- 'uq' : ('unsigned int', 64),
- 'sf' : ('float', 32),
- 'df' : ('float', 64)
-}};
-
-def operands {{
- # Int regs default to unsigned, but code should not count on this.
- # For clarity, descriptions that depend on unsigned behavior should
- # explicitly specify '.uq'.
- 'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
- 'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
- 'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
- 'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
- 'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
- 'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
- 'Mem': MemOperandTraits('uq', None,
- ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
- 'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
- 'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
- # The next two are hacks for non-full-system call-pal emulation
- 'R0': IntRegOperandTraits('uq', '0', None, 1),
- 'R16': IntRegOperandTraits('uq', '16', None, 1)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Basic instruction classes/templates/formats etc.
-//
-
-output header {{
-// uncomment the following to get SimpleScalar-compatible disassembly
-// (useful for diffing output traces).
-// #define SS_COMPATIBLE_DISASSEMBLY
-
- /**
- * Base class for all Alpha static instructions.
- */
- class AlphaStaticInst : public StaticInst<AlphaISA>
- {
- protected:
-
- /// Make AlphaISA register dependence tags directly visible in
- /// this class and derived classes. Maybe these should really
- /// live here and not in the AlphaISA namespace.
- enum DependenceTags {
- FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
- Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
- Uniq_DepTag = AlphaISA::Uniq_DepTag,
- IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
- };
-
- /// Constructor.
- AlphaStaticInst(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : StaticInst<AlphaISA>(mnem, _machInst, __opClass)
- {
- }
-
- /// Print a register name for disassembly given the unique
- /// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- void
- AlphaStaticInst::printReg(std::ostream &os, int reg) const
- {
- if (reg < FP_Base_DepTag) {
- ccprintf(os, "r%d", reg);
- }
- else {
- ccprintf(os, "f%d", reg - FP_Base_DepTag);
- }
- }
-
- std::string
- AlphaStaticInst::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();
- }
-}};
-
-// Declarations for execute() methods.
-def template BasicExecDeclare {{
- Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-// Basic instruction class declaration template.
-def template BasicDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)s(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-}};
-
-// Basic instruction class constructor template.
-def template BasicConstructor {{
- inline %(class_name)s::%(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-}};
-
-// Basic instruction class execute method template.
-def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// Basic decode template.
-def template BasicDecode {{
- return new %(class_name)s(machInst);
-}};
-
-// Basic decode template, passing mnemonic in as string arg to constructor.
-def template BasicDecodeWithMnemonic {{
- return new %(class_name)s("%(mnemonic)s", machInst);
-}};
-
-// The most basic instruction format... used only for a few misc. insts
-def format BasicOperate(code, *flags) {{
- iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Nop
-//
-
-output header {{
- /**
- * Static instruction class for no-ops. This is a leaf class.
- */
- class Nop : public AlphaStaticInst
- {
- /// Disassembly of original instruction.
- const std::string originalDisassembly;
-
- public:
- /// Constructor
- Nop(const std::string _originalDisassembly, MachInst _machInst)
- : AlphaStaticInst("nop", _machInst, No_OpClass),
- originalDisassembly(_originalDisassembly)
- {
- flags[IsNop] = true;
- }
-
- ~Nop() { }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- %(BasicExecDeclare)s
- };
-}};
-
-output decoder {{
- 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
- 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;
- }
-}};
-
-// integer & FP operate instructions use Rc as dest, so check for
-// Rc == 31 to detect nops
-def template OperateNopCheckDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (RC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// Like BasicOperate format, but generates NOP if RC/FC == 31
-def format BasicOperateWithNopCheck(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
- opt_args)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = OperateNopCheckDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Integer operate instructions
-//
-
-output header {{
- /**
- * Base class for integer immediate instructions.
- */
- class IntegerImm : public AlphaStaticInst
- {
- protected:
- /// Immediate operand value (unsigned 8-bit int).
- uint8_t imm;
-
- /// Constructor
- IntegerImm(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first source reg... if there's
- // a second one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
-
- ss << (int)imm;
-
- if (_numDestRegs > 0) {
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-}};
-
-
-def template RegOrImmDecode {{
- {
- AlphaStaticInst *i =
- (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
- : (AlphaStaticInst *)new %(class_name)s(machInst);
- if (RC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// Primary format for integer operate instructions:
-// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
-// - Generates NOP if RC == 31.
-def format IntegerOperate(code, *opt_flags) {{
- # If the code block contains 'Rb_or_imm', we define two instructions,
- # one using 'Rb' and one using 'imm', and have the decoder select
- # the right one.
- uses_imm = (code.find('Rb_or_imm') != -1)
- if uses_imm:
- orig_code = code
- # base code is reg version:
- # rewrite by substituting 'Rb' for 'Rb_or_imm'
- code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
- # generate immediate version by substituting 'imm'
- # note that imm takes no extenstion, so we extend
- # the regexp to replace any extension as well
- imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code)
-
- # generate declaration for register version
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BasicExecute.subst(iop)
-
- if uses_imm:
- # append declaration for imm version
- imm_cblk = CodeBlock(imm_code)
- imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
- opt_flags)
- header_output += BasicDeclare.subst(imm_iop)
- decoder_output += BasicConstructor.subst(imm_iop)
- exec_output += BasicExecute.subst(imm_iop)
- # decode checks IMM bit to pick correct version
- decode_block = RegOrImmDecode.subst(iop)
- else:
- # no imm version: just check for nop
- decode_block = OperateNopCheckDecode.subst(iop)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Floating-point instructions
-//
-// Note that many FP-type instructions which do not support all the
-// various rounding & trapping modes use the simpler format
-// BasicOperateWithNopCheck.
-//
-
-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.
-#if FULL_SYSTEM
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- Fault fault = No_Fault; // dummy... this ipr access should not fault
- if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
- fault = Fen_Fault;
- }
- return fault;
- }
-#else
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- return No_Fault;
- }
-#endif
-}};
-
-output header {{
- /**
- * Base class for general floating-point instructions. Includes
- * support for various Alpha rounding and trapping modes. Only FP
- * instructions that require this support are derived from this
- * class; the rest derive directly from AlphaStaticInst.
- */
- class AlphaFP : public AlphaStaticInst
- {
- public:
- /// Alpha FP rounding modes.
- enum RoundingMode {
- Chopped = 0, ///< round toward zero
- Minus_Infinity = 1, ///< round toward minus infinity
- Normal = 2, ///< round to nearest (default)
- Dynamic = 3, ///< use FPCR setting (in instruction)
- Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
- };
-
- /// Alpha FP trapping modes.
- /// For instructions that produce integer results, the
- /// "Underflow Enable" modes really mean "Overflow Enable", and
- /// the assembly modifier is V rather than U.
- enum TrappingMode {
- /// default: nothing enabled
- Imprecise = 0, ///< no modifier
- /// underflow/overflow traps enabled, inexact disabled
- Underflow_Imprecise = 1, ///< /U or /V
- Underflow_Precise = 5, ///< /SU or /SV
- /// underflow/overflow and inexact traps enabled
- Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
- };
-
- protected:
- /// Map Alpha rounding mode to C99 constants from <fenv.h>.
- static const int alphaToC99RoundingMode[];
-
- /// Map enum RoundingMode values to disassembly suffixes.
- static const char *roundingModeSuffix[];
- /// Map enum TrappingMode values to FP disassembly suffixes.
- static const char *fpTrappingModeSuffix[];
- /// Map enum TrappingMode values to integer disassembly suffixes.
- static const char *intTrappingModeSuffix[];
-
- /// This instruction's rounding mode.
- RoundingMode roundingMode;
- /// This instruction's trapping mode.
- TrappingMode trappingMode;
-
- /// Have we warned about this instruction's unsupported
- /// rounding mode (if applicable)?
- mutable bool warnedOnRounding;
-
- /// Have we warned about this instruction's unsupported
- /// trapping mode (if applicable)?
- mutable bool warnedOnTrapping;
-
- /// Constructor
- AlphaFP(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- roundingMode((enum RoundingMode)FP_ROUNDMODE),
- trappingMode((enum TrappingMode)FP_TRAPMODE),
- warnedOnRounding(false),
- warnedOnTrapping(false)
- {
- }
-
- int getC99RoundingMode(uint64_t fpcr_val) const;
-
- // This differs from the AlphaStaticInst version only in
- // printing suffixes for non-default rounding & trapping modes.
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
-}};
-
-
-output decoder {{
- int
- AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
- {
- if (roundingMode == Dynamic) {
- return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
- }
- else {
- return alphaToC99RoundingMode[roundingMode];
- }
- }
-
- std::string
- AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::string mnem_str(mnemonic);
-
-#ifndef SS_COMPATIBLE_DISASSEMBLY
- std::string suffix("");
- suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
- ? fpTrappingModeSuffix[trappingMode]
- : intTrappingModeSuffix[trappingMode]);
- suffix += roundingModeSuffix[roundingMode];
-
- if (suffix != "") {
- mnem_str = csprintf("%s/%s", mnemonic, suffix);
- }
-#endif
-
- std::stringstream ss;
- ccprintf(ss, "%-10s ", mnem_str.c_str());
-
- // 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();
- }
-
- const int AlphaFP::alphaToC99RoundingMode[] = {
- FE_TOWARDZERO, // Chopped
- FE_DOWNWARD, // Minus_Infinity
- FE_TONEAREST, // Normal
- FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
- };
-
- const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
- // mark invalid trapping modes, but don't fail on them, because
- // you could decode anything on a misspeculated path
- const char *AlphaFP::fpTrappingModeSuffix[] =
- { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
- const char *AlphaFP::intTrappingModeSuffix[] =
- { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
-}};
-
-// FP instruction class execute method template. Handles non-standard
-// rounding modes.
-def template FloatingPointExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (trappingMode != Imprecise && !warnedOnTrapping) {
- warn("%s: non-standard trapping mode not supported",
- generateDisassembly(0, NULL));
- warnedOnTrapping = true;
- }
-
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
-#if USE_FENV
- if (roundingMode == Normal) {
- %(code)s;
- } else {
- fesetround(getC99RoundingMode(xc->readFpcr()));
- %(code)s;
- fesetround(FE_TONEAREST);
- }
-#else
- if (roundingMode != Normal && !warnedOnRounding) {
- warn("%s: non-standard rounding mode not supported",
- generateDisassembly(0, NULL));
- warnedOnRounding = true;
- }
- %(code)s;
-#endif
-
- if (fault == No_Fault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// FP instruction class execute method template where no dynamic
-// rounding mode control is needed. Like BasicExecute, but includes
-// check & warning for non-standard trapping mode.
-def template FPFixedRoundingExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (trappingMode != Imprecise && !warnedOnTrapping) {
- warn("%s: non-standard trapping mode not supported",
- generateDisassembly(0, NULL));
- warnedOnTrapping = true;
- }
-
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-def template FloatingPointDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (FC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// General format for floating-point operate instructions:
-// - Checks trapping and rounding mode flags. Trapping modes
-// currently unimplemented (will fail).
-// - Generates NOP if FC == 31.
-def format FloatingPointOperate(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
- decode_block = FloatingPointDecode.subst(iop)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = FloatingPointExecute.subst(iop)
-}};
-
-// Special format for cvttq where rounding mode is pre-decoded
-def format FPFixedRounding(code, class_suffix, *opt_args) {{
- Name += class_suffix
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
- decode_block = FloatingPointDecode.subst(iop)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = FPFixedRoundingExecute.subst(iop)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Memory-format instructions: LoadAddress, Load, Store
-//
-
-output header {{
- /**
- * Base class for general Alpha memory-format instructions.
- */
- class Memory : public AlphaStaticInst
- {
- protected:
-
- /// Memory request flags. See mem_req_base.hh.
- unsigned memAccessFlags;
- /// Pointer to EAComp object.
- const StaticInstPtr<AlphaISA> eaCompPtr;
- /// Pointer to MemAcc object.
- const StaticInstPtr<AlphaISA> memAccPtr;
-
- /// Constructor
- Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- public:
-
- const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
- const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
- };
-
- /**
- * Base class for memory-format instructions using a 32-bit
- * displacement (i.e. most of them).
- */
- class MemoryDisp32 : public Memory
- {
- protected:
- /// Displacement for EA calculation (signed).
- int32_t disp;
-
- /// Constructor.
- MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
- disp(MEMDISP)
- {
- }
- };
-
-
- /**
- * Base class for a few miscellaneous memory-format insts
- * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
- * None of these instructions has a destination register either.
- */
- class MemoryNoDisp : public Memory
- {
- protected:
- /// Constructor
- MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-
-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);
- }
-
- std::string
- MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (r%d)", mnemonic, 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:
-
- /**
- * "Fake" effective address computation class for "%(mnemonic)s".
- */
- class EAComp : public %(base_class)s
- {
- public:
- /// Constructor
- EAComp(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- /**
- * "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
- };
-}};
-
-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 = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(op_wb)s;
- xc->setEA(EA);
- }
-
- return fault;
- }
-}};
-
-def template MemAccExecute {{
- Fault
- %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_nonmem_rd)s;
- EA = xc->getEA();
-
- if (fault == No_Fault) {
- %(op_mem_rd)s;
- %(code)s;
- }
-
- if (fault == No_Fault) {
- %(op_mem_wb)s;
- }
-
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(op_nonmem_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template LoadStoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- %(op_mem_rd)s;
- %(memacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(op_mem_wb)s;
- }
-
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(op_nonmem_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template PrefetchExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- xc->prefetch(EA, memAccessFlags);
- }
-
- return No_Fault;
- }
-}};
-
-// load instructions use Ra as dest, so check for
-// Ra == 31 to detect nops
-def template LoadNopCheckDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (RA == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-
-// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
-def template LoadPrefetchCheckDecode {{
- {
- if (RA != 31) {
- return new %(class_name)s(machInst);
- }
- else {
- return new %(class_name)sPrefetch(machInst);
- }
- }
-}};
-
-
-let {{
-def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
- base_class = 'MemoryDisp32', flags = [],
- decode_template = BasicDecode,
- exec_template = LoadStoreExecute):
- # Segregate flags into instruction flags (handled by InstObjParams)
- # and memory access flags (handled here).
-
- # Would be nice to autogenerate this list, but oh well.
- valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
- mem_flags = [f for f in flags if f in valid_mem_flags]
- inst_flags = [f for f in flags if f not in valid_mem_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 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
-
- # (header_output, decoder_output, decode_block, exec_output)
- return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
- decode_template.subst(iop),
- EACompExecute.subst(ea_iop)
- + MemAccExecute.subst(memacc_iop)
- + exec_template.subst(iop))
-}};
-
-
-def format LoadOrNop(ea_code, memacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
- decode_template = LoadNopCheckDecode)
-}};
-
-
-// Note that the flags passed in apply only to the prefetch version
-def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
- # declare the load instruction object and generate the decode block
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code,
- decode_template = LoadPrefetchCheckDecode)
-
- # Declare the prefetch instruction object.
-
- # convert flags from tuple to list to make them mutable
- pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
-
- (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
- LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
- flags = pf_flags, exec_template = PrefetchExecute)
-
- header_output += pf_header_output
- decoder_output += pf_decoder_output
- exec_output += pf_exec_output
-}};
-
-
-def format Store(ea_code, memacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags)
-}};
-
-
-def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
- flags = flags)
-}};
-
-
-// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
-def format MiscPrefetch(ea_code, memacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
- base_class = 'MemoryNoDisp')
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Control transfer instructions
-//
-
-output header {{
-
- /**
- * 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 AlphaStaticInst
- {
- 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)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- cachedPC(0), cachedSymtab(0)
- {
- }
-
- const std::string &
- disassemble(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for branches (PC-relative control transfers),
- * conditional or unconditional.
- */
- class Branch : public PCDependentDisassembly
- {
- protected:
- /// Displacement to target address (signed).
- int32_t disp;
-
- /// Constructor.
- Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(BRDISP << 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 Alpha 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(BRDISP)
- {
- }
-
- Addr branchTarget(ExecContext *xc) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- Addr
- Branch::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)
- {
- 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
- 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 template JumpOrBranchDecode {{
- return (RA == 31)
- ? (StaticInst<AlphaISA> *)new %(class_name)s(machInst)
- : (StaticInst<AlphaISA> *)new %(class_name)sAndLink(machInst);
-}};
-
-def format CondBranch(code) {{
- code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\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)
-}};
-
-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 format UncondBranch(*flags) {{
- flags += ('IsUncondControl', 'IsDirectControl')
- (header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
-}};
-
-def format Jump(*flags) {{
- flags += ('IsUncondControl', 'IsIndirectControl')
- (header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// PAL calls
-//
-
-output header {{
- /**
- * Base class for emulated call_pal calls (used only in
- * non-full-system mode).
- */
- class EmulatedCallPal : public AlphaStaticInst
- {
- protected:
-
- /// Constructor.
- EmulatedCallPal(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- EmulatedCallPal::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%s %s", "call_pal", mnemonic);
-#else
- return csprintf("%-10s %s", "call_pal", mnemonic);
-#endif
- }
-}};
-
-def format EmulatedCallPal(code, *flags) {{
- iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-output header {{
- /**
- * Base class for full-system-mode call_pal instructions.
- * Probably could turn this into a leaf class and get rid of the
- * parser template.
- */
- class CallPalBase : public AlphaStaticInst
- {
- protected:
- int palFunc; ///< Function code part of instruction
- int palOffset; ///< Target PC, offset from IPR_PAL_BASE
- bool palValid; ///< is the function code valid?
- bool palPriv; ///< is this call privileged?
-
- /// Constructor.
- CallPalBase(const char *mnem, MachInst _machInst,
- OpClass __opClass);
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- inline
- CallPalBase::CallPalBase(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- palFunc(PALFUNC)
- {
- // From the 21164 HRM (paraphrased):
- // Bit 7 of the function code (mask 0x80) indicates
- // whether the call is privileged (bit 7 == 0) or
- // unprivileged (bit 7 == 1). The privileged call table
- // starts at 0x2000, the unprivielged call table starts at
- // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
- // offset.
- const int palPrivMask = 0x80;
- const int palOffsetMask = 0x3f;
-
- // Pal call is invalid unless all other bits are 0
- palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
- palPriv = ((machInst & palPrivMask) == 0);
- int shortPalFunc = (machInst & palOffsetMask);
- // Add 1 to base to set pal-mode bit
- palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
- }
-
- std::string
- CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s %#x", "call_pal", palFunc);
- }
-}};
-
-def format CallPal(code, *flags) {{
- iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// hw_ld, hw_st
-//
-
-output header {{
- /**
- * Base class for hw_ld and hw_st.
- */
- class HwLoadStore : public Memory
- {
- protected:
-
- /// Displacement for EA calculation (signed).
- int16_t disp;
-
- /// Constructor
- HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr);
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-
-output decoder {{
- inline
- HwLoadStore::HwLoadStore(const char *mnem, MachInst _machInst,
- OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr,
- StaticInstPtr<AlphaISA> _memAccPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
- disp(HW_LDST_DISP)
- {
- memAccessFlags = 0;
- if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
- if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
- if (HW_LDST_VPTE) memAccessFlags |= VPTE;
- if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
- }
-
- std::string
- HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
-#else
- // HW_LDST_LOCK and HW_LDST_COND are the same bit.
- const char *lock_str =
- (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
-
- return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
- mnemonic, RA, disp, RB,
- HW_LDST_PHYS ? ",PHYS" : "",
- HW_LDST_ALT ? ",ALT" : "",
- HW_LDST_QUAD ? ",QUAD" : "",
- HW_LDST_VPTE ? ",VPTE" : "",
- lock_str);
-#endif
- }
-}};
-
-def format HwLoadStore(ea_code, memacc_code, class_ext, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- flags = flags, base_class = 'HwLoadStore')
-}};
-
-
-def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- postacc_code, flags = flags, base_class = 'HwLoadStore')
-}};
-
-
-output header {{
- /**
- * Base class for hw_mfpr and hw_mtpr.
- */
- class HwMoveIPR : public AlphaStaticInst
- {
- protected:
- /// Index of internal processor register.
- int ipr_index;
-
- /// Constructor
- HwMoveIPR(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- ipr_index(HW_IPR_IDX)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- if (_numSrcRegs > 0) {
- // must be mtpr
- return csprintf("%-10s r%d,IPR(%#x)",
- mnemonic, RA, ipr_index);
- }
- else {
- // must be mfpr
- return csprintf("%-10s IPR(%#x),r%d",
- mnemonic, ipr_index, RA);
- }
- }
-}};
-
-def format HwMoveIPR(code) {{
- iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
- ['IprAccessOp'])
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Unimplemented instructions
-//
-
-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 AlphaStaticInst
- {
- public:
- /// Constructor
- FailUnimplemented(const char *_mnemonic, MachInst _machInst)
- : AlphaStaticInst(_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 AlphaStaticInst
- {
- private:
- /// Have we warned on this instruction yet?
- mutable bool warned;
-
- public:
- /// Constructor
- WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
- : AlphaStaticInst(_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 AlphaStaticInst
- {
- public:
- /// Constructor
- Unknown(MachInst _machInst)
- : AlphaStaticInst("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;
- };
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Unknown instructions
-//
-
-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'
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Utility functions for execute methods
-//
-
-output exec {{
-
- /// Return opa + opb, summing carry into third arg.
- inline uint64_t
- addc(uint64_t opa, uint64_t opb, int &carry)
- {
- uint64_t res = opa + opb;
- if (res < opa || res < opb)
- ++carry;
- return res;
- }
-
- /// Multiply two 64-bit values (opa * opb), returning the 128-bit
- /// product in res_hi and res_lo.
- inline void
- mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
- {
- // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
- uint64_t opa_hi = opa<63:32>;
- uint64_t opa_lo = opa<31:0>;
- uint64_t opb_hi = opb<63:32>;
- uint64_t opb_lo = opb<31:0>;
-
- res_lo = opa_lo * opb_lo;
-
- // The middle partial products logically belong in bit
- // positions 95 to 32. Thus the lower 32 bits of each product
- // sum into the upper 32 bits of the low result, while the
- // upper 32 sum into the low 32 bits of the upper result.
- uint64_t partial1 = opa_hi * opb_lo;
- uint64_t partial2 = opa_lo * opb_hi;
-
- uint64_t partial1_lo = partial1<31:0> << 32;
- uint64_t partial1_hi = partial1<63:32>;
- uint64_t partial2_lo = partial2<31:0> << 32;
- uint64_t partial2_hi = partial2<63:32>;
-
- // Add partial1_lo and partial2_lo to res_lo, keeping track
- // of any carries out
- int carry_out = 0;
- res_lo = addc(partial1_lo, res_lo, carry_out);
- res_lo = addc(partial2_lo, res_lo, carry_out);
-
- // Now calculate the high 64 bits...
- res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out;
- }
-
- /// Map 8-bit S-floating exponent to 11-bit T-floating exponent.
- /// See Table 2-2 of Alpha AHB.
- inline int
- map_s(int old_exp)
- {
- int hibit = old_exp<7:>;
- int lobits = old_exp<6:0>;
-
- if (hibit == 1) {
- return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits);
- }
- else {
- return (lobits == 0) ? 0 : (0x380 | lobits);
- }
- }
-
- /// Convert a 32-bit S-floating value to the equivalent 64-bit
- /// representation to be stored in an FP reg.
- inline uint64_t
- s_to_t(uint32_t s_val)
- {
- uint64_t tmp = s_val;
- return (tmp<31:> << 63 // sign bit
- | (uint64_t)map_s(tmp<30:23>) << 52 // exponent
- | tmp<22:0> << 29); // fraction
- }
-
- /// Convert a 64-bit T-floating value to the equivalent 32-bit
- /// S-floating representation to be stored in memory.
- inline int32_t
- t_to_s(uint64_t t_val)
- {
- return (t_val<63:62> << 30 // sign bit & hi exp bit
- | t_val<58:29>); // rest of exp & fraction
- }
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// The actual decoder specification
-//
-
-decode OPCODE default Unknown::unknown() {
-
- format LoadAddress {
- 0x08: lda({{ Ra = Rb + disp; }});
- 0x09: ldah({{ Ra = Rb + (disp << 16); }});
- }
-
- format LoadOrNop {
- 0x0a: ldbu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.ub; }});
- 0x0c: ldwu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uw; }});
- 0x0b: ldq_u({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }});
- 0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
- 0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
- 0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
- 0x20: copy_load({{EA = Ra;}},
- {{fault = xc->copySrcTranslate(EA);}},
- IsMemRef, IsLoad, IsCopy);
- }
-
- format LoadOrPrefetch {
- 0x28: ldl({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }});
- 0x29: ldq({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, EVICT_NEXT);
- // IsFloating flag on lds gets the prefetch to disassemble
- // using f31 instead of r31... funcitonally it's unnecessary
- 0x22: lds({{ EA = Rb + disp; }}, {{ Fa.uq = s_to_t(Mem.ul); }},
- PF_EXCLUSIVE, IsFloating);
- }
-
- format Store {
- 0x0e: stb({{ EA = Rb + disp; }}, {{ Mem.ub = Ra<7:0>; }});
- 0x0d: stw({{ EA = Rb + disp; }}, {{ Mem.uw = Ra<15:0>; }});
- 0x2c: stl({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }});
- 0x2d: stq({{ EA = Rb + disp; }}, {{ Mem.uq = Ra.uq; }});
- 0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
- 0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
- 0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
- 0x24: copy_store({{EA = Rb;}},
- {{fault = xc->copy(EA);}},
- IsMemRef, IsStore, IsCopy);
- }
-
- format StoreCond {
- 0x2e: stl_c({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }},
- {{
- uint64_t tmp = Mem_write_result;
- // see stq_c
- Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
- }}, LOCKED);
- 0x2f: stq_c({{ EA = Rb + disp; }}, {{ Mem.uq = Ra; }},
- {{
- uint64_t tmp = Mem_write_result;
- // If the write operation returns 0 or 1, then
- // this was a conventional store conditional,
- // and the value indicates the success/failure
- // of the operation. If another value is
- // returned, then this was a Turbolaser
- // mailbox access, and we don't update the
- // result register at all.
- Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
- }}, LOCKED);
- }
-
- format IntegerOperate {
-
- 0x10: decode INTFUNC { // integer arithmetic operations
-
- 0x00: addl({{ Rc.sl = Ra.sl + Rb_or_imm.sl; }});
- 0x40: addlv({{
- uint32_t tmp = Ra.sl + Rb_or_imm.sl;
- // 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;
- Rc.sl = tmp;
- }});
- 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }});
- 0x12: s8addl({{ Rc.sl = (Ra.sl << 3) + Rb_or_imm.sl; }});
-
- 0x20: addq({{ Rc = Ra + Rb_or_imm; }});
- 0x60: addqv({{
- uint64_t tmp = Ra + Rb_or_imm;
- // 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;
- Rc = tmp;
- }});
- 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }});
- 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }});
-
- 0x09: subl({{ Rc.sl = Ra.sl - Rb_or_imm.sl; }});
- 0x49: sublv({{
- uint32_t tmp = Ra.sl - Rb_or_imm.sl;
- // signed overflow detection is same as for add,
- // except we need to look at the *complemented*
- // 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;
- Rc.sl = tmp;
- }});
- 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }});
- 0x1b: s8subl({{ Rc.sl = (Ra.sl << 3) - Rb_or_imm.sl; }});
-
- 0x29: subq({{ Rc = Ra - Rb_or_imm; }});
- 0x69: subqv({{
- uint64_t tmp = Ra - Rb_or_imm;
- // signed overflow detection is same as for add,
- // except we need to look at the *complemented*
- // 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;
- Rc = tmp;
- }});
- 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }});
- 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }});
-
- 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }});
- 0x6d: cmple({{ Rc = (Ra.sq <= Rb_or_imm.sq); }});
- 0x4d: cmplt({{ Rc = (Ra.sq < Rb_or_imm.sq); }});
- 0x3d: cmpule({{ Rc = (Ra.uq <= Rb_or_imm.uq); }});
- 0x1d: cmpult({{ Rc = (Ra.uq < Rb_or_imm.uq); }});
-
- 0x0f: cmpbge({{
- int hi = 7;
- int lo = 0;
- uint64_t tmp = 0;
- for (int i = 0; i < 8; ++i) {
- tmp |= (Ra.uq<hi:lo> >= Rb_or_imm.uq<hi:lo>) << i;
- hi += 8;
- lo += 8;
- }
- Rc = tmp;
- }});
- }
-
- 0x11: decode INTFUNC { // integer logical operations
-
- 0x00: and({{ Rc = Ra & Rb_or_imm; }});
- 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }});
- 0x20: bis({{ Rc = Ra | Rb_or_imm; }});
- 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }});
- 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }});
- 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }});
-
- // conditional moves
- 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }});
- 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }});
- 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }});
- 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }});
- 0x44: cmovlt({{ Rc = (Ra.sq < 0) ? Rb_or_imm : Rc; }});
- 0x46: cmovge({{ Rc = (Ra.sq >= 0) ? Rb_or_imm : Rc; }});
- 0x64: cmovle({{ Rc = (Ra.sq <= 0) ? Rb_or_imm : Rc; }});
- 0x66: cmovgt({{ Rc = (Ra.sq > 0) ? Rb_or_imm : Rc; }});
-
- // For AMASK, RA must be R31.
- 0x61: decode RA {
- 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }});
- }
-
- // For IMPLVER, RA must be R31 and the B operand
- // must be the immediate value 1.
- 0x6c: decode RA {
- 31: decode IMM {
- 1: decode INTIMM {
- // return EV5 for FULL_SYSTEM and EV6 otherwise
- 1: implver({{
-#if FULL_SYSTEM
- Rc = 1;
-#else
- Rc = 2;
-#endif
- }});
- }
- }
- }
-
-#if FULL_SYSTEM
- // The mysterious 11.25...
- 0x25: WarnUnimpl::eleven25();
-#endif
- }
-
- 0x12: decode INTFUNC {
- 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }});
- 0x34: srl({{ Rc = Ra.uq >> Rb_or_imm<5:0>; }});
- 0x3c: sra({{ Rc = Ra.sq >> Rb_or_imm<5:0>; }});
-
- 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }});
- 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }});
- 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }});
- 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }});
-
- 0x52: mskwh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra;
- }});
- 0x62: msklh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra;
- }});
- 0x72: mskqh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra;
- }});
-
- 0x06: extbl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }});
- 0x16: extwl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<15:0>; }});
- 0x26: extll({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<31:0>; }});
- 0x36: extql({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8)); }});
-
- 0x5a: extwh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }});
- 0x6a: extlh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }});
- 0x7a: extqh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }});
-
- 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }});
- 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }});
- 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }});
- 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }});
-
- 0x57: inswh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq<15:0> >> (64 - 8 * bv)) : 0;
- }});
- 0x67: inslh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq<31:0> >> (64 - 8 * bv)) : 0;
- }});
- 0x77: insqh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq >> (64 - 8 * bv)) : 0;
- }});
-
- 0x30: zap({{
- uint64_t zapmask = 0;
- for (int i = 0; i < 8; ++i) {
- if (Rb_or_imm<i:>)
- zapmask |= (mask(8) << (i * 8));
- }
- Rc = Ra & ~zapmask;
- }});
- 0x31: zapnot({{
- uint64_t zapmask = 0;
- for (int i = 0; i < 8; ++i) {
- if (!Rb_or_imm<i:>)
- zapmask |= (mask(8) << (i * 8));
- }
- Rc = Ra & ~zapmask;
- }});
- }
-
- 0x13: decode INTFUNC { // integer multiplies
- 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
- 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
- 0x30: umulh({{
- uint64_t hi, lo;
- mul128(Ra, Rb_or_imm, hi, lo);
- Rc = hi;
- }}, IntMultOp);
- 0x40: mullv({{
- // 32-bit multiply with trap on overflow
- int64_t Rax = Ra.sl; // sign extended version of Ra.sl
- int64_t Rbx = Rb_or_imm.sl;
- int64_t tmp = Rax * Rbx;
- // To avoid overflow, all the upper 32 bits must match
- // the sign bit of the lower 32. We code this as
- // 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;
- Rc.sl = tmp<31:0>;
- }}, IntMultOp);
- 0x60: mulqv({{
- // 64-bit multiply with trap on overflow
- uint64_t hi, lo;
- mul128(Ra, Rb_or_imm, hi, lo);
- // all the upper 64 bits must match the sign bit of
- // the lower 64
- if (!((hi == 0 && lo<63:> == 0) ||
- (hi == mask(64) && lo<63:> == 1)))
- fault = Integer_Overflow_Fault;
- Rc = lo;
- }}, IntMultOp);
- }
-
- 0x1c: decode INTFUNC {
- 0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
- 0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
- 0x32: ctlz({{
- uint64_t count = 0;
- uint64_t temp = Rb;
- if (temp<63:32>) temp >>= 32; else count += 32;
- if (temp<31:16>) temp >>= 16; else count += 16;
- if (temp<15:8>) temp >>= 8; else count += 8;
- if (temp<7:4>) temp >>= 4; else count += 4;
- if (temp<3:2>) temp >>= 2; else count += 2;
- if (temp<1:1>) temp >>= 1; else count += 1;
- if ((temp<0:0>) != 0x1) count += 1;
- Rc = count;
- }}, IntAluOp);
-
- 0x33: cttz({{
- uint64_t count = 0;
- uint64_t temp = Rb;
- if (!(temp<31:0>)) { temp >>= 32; count += 32; }
- if (!(temp<15:0>)) { temp >>= 16; count += 16; }
- if (!(temp<7:0>)) { temp >>= 8; count += 8; }
- if (!(temp<3:0>)) { temp >>= 4; count += 4; }
- if (!(temp<1:0>)) { temp >>= 2; count += 2; }
- if (!(temp<0:0> & ULL(0x1))) count += 1;
- Rc = count;
- }}, IntAluOp);
-
- format FailUnimpl {
- 0x30: ctpop();
- 0x31: perr();
- 0x34: unpkbw();
- 0x35: unpkbl();
- 0x36: pkwb();
- 0x37: pklb();
- 0x38: minsb8();
- 0x39: minsw4();
- 0x3a: minub8();
- 0x3b: minuw4();
- 0x3c: maxub8();
- 0x3d: maxuw4();
- 0x3e: maxsb8();
- 0x3f: maxsw4();
- }
-
- format BasicOperateWithNopCheck {
- 0x70: decode RB {
- 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
- }
- 0x78: decode RB {
- 31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
- FloatCvtOp);
- }
- }
- }
- }
-
- // Conditional branches.
- format CondBranch {
- 0x39: beq({{ cond = (Ra == 0); }});
- 0x3d: bne({{ cond = (Ra != 0); }});
- 0x3e: bge({{ cond = (Ra.sq >= 0); }});
- 0x3f: bgt({{ cond = (Ra.sq > 0); }});
- 0x3b: ble({{ cond = (Ra.sq <= 0); }});
- 0x3a: blt({{ cond = (Ra.sq < 0); }});
- 0x38: blbc({{ cond = ((Ra & 1) == 0); }});
- 0x3c: blbs({{ cond = ((Ra & 1) == 1); }});
-
- 0x31: fbeq({{ cond = (Fa == 0); }});
- 0x35: fbne({{ cond = (Fa != 0); }});
- 0x36: fbge({{ cond = (Fa >= 0); }});
- 0x37: fbgt({{ cond = (Fa > 0); }});
- 0x33: fble({{ cond = (Fa <= 0); }});
- 0x32: fblt({{ cond = (Fa < 0); }});
- }
-
- // unconditional branches
- format UncondBranch {
- 0x30: br();
- 0x34: bsr(IsCall);
- }
-
- // indirect branches
- 0x1a: decode JMPFUNC {
- format Jump {
- 0: jmp();
- 1: jsr(IsCall);
- 2: ret(IsReturn);
- 3: jsr_coroutine(IsCall, IsReturn);
- }
- }
-
- // Square root and integer-to-FP moves
- 0x14: decode FP_SHORTFUNC {
- // Integer to FP register moves must have RB == 31
- 0x4: decode RB {
- 31: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
- 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
- 0x014: FailUnimpl::itoff(); // VAX-format conversion
- }
- }
- }
-
- // Square root instructions must have FA == 31
- 0xb: decode FA {
- 31: decode FP_TYPEFUNC {
- format FloatingPointOperate {
-#if SS_COMPATIBLE_FP
- 0x0b: sqrts({{
- if (Fb < 0.0)
- fault = Arithmetic_Fault;
- Fc = sqrt(Fb);
- }}, FloatSqrtOp);
-#else
- 0x0b: sqrts({{
- if (Fb.sf < 0.0)
- fault = Arithmetic_Fault;
- Fc.sf = sqrt(Fb.sf);
- }}, FloatSqrtOp);
-#endif
- 0x2b: sqrtt({{
- if (Fb < 0.0)
- fault = Arithmetic_Fault;
- Fc = sqrt(Fb);
- }}, FloatSqrtOp);
- }
- }
- }
-
- // VAX-format sqrtf and sqrtg are not implemented
- 0xa: FailUnimpl::sqrtfg();
- }
-
- // IEEE floating point
- 0x16: decode FP_SHORTFUNC_TOP2 {
- // The top two bits of the short function code break this
- // space into four groups: binary ops, compares, reserved, and
- // conversions. See Table 4-12 of AHB. There are different
- // special cases in these different groups, so we decode on
- // these top two bits first just to select a decode strategy.
- // Most of these instructions may have various trapping and
- // rounding mode flags set; these are decoded in the
- // FloatingPointDecode template used by the
- // FloatingPointOperate format.
-
- // add/sub/mul/div: just decode on the short function code
- // and source type. All valid trapping and rounding modes apply.
- 0: decode FP_TRAPMODE {
- // check for valid trapping modes here
- 0,1,5,7: decode FP_TYPEFUNC {
- format FloatingPointOperate {
-#if SS_COMPATIBLE_FP
- 0x00: adds({{ Fc = Fa + Fb; }});
- 0x01: subs({{ Fc = Fa - Fb; }});
- 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
- 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
-#else
- 0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
- 0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
- 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
- 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
-#endif
-
- 0x20: addt({{ Fc = Fa + Fb; }});
- 0x21: subt({{ Fc = Fa - Fb; }});
- 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
- 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
- }
- }
- }
-
- // Floating-point compare instructions must have the default
- // rounding mode, and may use the default trapping mode or
- // /SU. Both trapping modes are treated the same by M5; the
- // only difference on the real hardware (as far a I can tell)
- // is that without /SU you'd get an imprecise trap if you
- // tried to compare a NaN with something else (instead of an
- // "unordered" result).
- 1: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a4, 0x5a4: cmptun({{ // unordered
- Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
- }}, FloatCmpOp);
- }
- }
-
- // The FP-to-integer and integer-to-FP conversion insts
- // require that FA be 31.
- 3: decode FA {
- 31: decode FP_TYPEFUNC {
- format FloatingPointOperate {
- 0x2f: decode FP_ROUNDMODE {
- format FPFixedRounding {
- // "chopped" i.e. round toward zero
- 0: cvttq({{ Fc.sq = (int64_t)trunc(Fb); }},
- Chopped);
- // round to minus infinity
- 1: cvttq({{ Fc.sq = (int64_t)floor(Fb); }},
- MinusInfinity);
- }
- default: cvttq({{ Fc.sq = (int64_t)nearbyint(Fb); }});
- }
-
- // The cvtts opcode is overloaded to be cvtst if the trap
- // mode is 2 or 6 (which are not valid otherwise)
- 0x2c: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- // trap on denorm version "cvtst/s" is
- // simulated same as cvtst
- 0x2ac, 0x6ac: cvtst({{ Fc = Fb.sf; }});
- }
- default: cvtts({{ Fc.sf = Fb; }});
- }
-
- // The trapping mode for integer-to-FP conversions
- // must be /SUI or nothing; /U and /SU are not
- // allowed. The full set of rounding modes are
- // supported though.
- 0x3c: decode FP_TRAPMODE {
- 0,7: cvtqs({{ Fc.sf = Fb.sq; }});
- }
- 0x3e: decode FP_TRAPMODE {
- 0,7: cvtqt({{ Fc = Fb.sq; }});
- }
- }
- }
- }
- }
-
- // misc FP operate
- 0x17: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x010: cvtlq({{
- Fc.sl = (Fb.uq<63:62> << 30) | Fb.uq<58:29>;
- }});
- 0x030: cvtql({{
- Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
- }});
-
- // We treat the precise & imprecise trapping versions of
- // cvtql identically.
- 0x130, 0x530: cvtqlv({{
- // To avoid overflow, all the upper 32 bits must match
- // the sign bit of the lower 32. We code this as
- // 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;
- Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
- }});
-
- 0x020: cpys({{ // copy sign
- Fc.uq = (Fa.uq<63:> << 63) | Fb.uq<62:0>;
- }});
- 0x021: cpysn({{ // copy sign negated
- Fc.uq = (~Fa.uq<63:> << 63) | Fb.uq<62:0>;
- }});
- 0x022: cpyse({{ // copy sign and exponent
- Fc.uq = (Fa.uq<63:52> << 52) | Fb.uq<51:0>;
- }});
-
- 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }});
- 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }});
- 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }});
- 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }});
- 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }});
- 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }});
-
- 0x024: mt_fpcr({{ FPCR = Fa.uq; }});
- 0x025: mf_fpcr({{ Fa.uq = FPCR; }});
- }
- }
-
- // miscellaneous mem-format ops
- 0x18: decode MEMFUNC {
- format WarnUnimpl {
- 0x8000: fetch();
- 0xa000: fetch_m();
- 0xe800: ecb();
- }
-
- format MiscPrefetch {
- 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
- {{ xc->writeHint(EA, 64, memAccessFlags); }},
- IsMemRef, IsDataPrefetch, IsStore, MemWriteOp,
- NO_FAULT);
- }
-
- format BasicOperate {
- 0xc000: rpcc({{
-#if FULL_SYSTEM
- /* Rb is a fake dependency so here is a fun way to get
- * the parser to understand that.
- */
- Ra = xc->readIpr(AlphaISA::IPR_CC, fault) + (Rb & 0);
-
-#else
- Ra = curTick;
-#endif
- }});
-
- // All of the barrier instructions below do nothing in
- // their execute() methods (hence the empty code blocks).
- // All of their functionality is hard-coded in the
- // pipeline based on the flags IsSerializing,
- // IsMemBarrier, and IsWriteBarrier. In the current
- // detailed CPU model, the execute() function only gets
- // called at fetch, so there's no way to generate pipeline
- // behavior at any other stage. Once we go to an
- // exec-in-exec CPU model we should be able to get rid of
- // these flags and implement this behavior via the
- // execute() methods.
-
- // trapb is just a barrier on integer traps, where excb is
- // a barrier on integer and FP traps. "EXCB is thus a
- // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
- // them the same though.
- 0x0000: trapb({{ }}, IsSerializing, No_OpClass);
- 0x0400: excb({{ }}, IsSerializing, No_OpClass);
- 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
- 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
- }
-
-#if FULL_SYSTEM
- format BasicOperate {
- 0xe000: rc({{
- Ra = xc->readIntrFlag();
- xc->setIntrFlag(0);
- }}, IsNonSpeculative);
- 0xf000: rs({{
- Ra = xc->readIntrFlag();
- xc->setIntrFlag(1);
- }}, IsNonSpeculative);
- }
-#else
- format FailUnimpl {
- 0xe000: rc();
- 0xf000: rs();
- }
-#endif
- }
-
-#if FULL_SYSTEM
- 0x00: CallPal::call_pal({{
- if (!palValid ||
- (palPriv
- && 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;
- }
- else {
- // check to see if simulator wants to do something special
- // on this PAL call (including maybe suppress it)
- bool dopal = xc->simPalCheck(palFunc);
-
- if (dopal) {
- AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
- xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
- NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
- }
- }
- }}, IsNonSpeculative);
-#else
- 0x00: decode PALFUNC {
- format EmulatedCallPal {
- 0x00: halt ({{
- SimExit(curTick, "halt instruction encountered");
- }}, IsNonSpeculative);
- 0x83: callsys({{
- xc->syscall();
- }}, IsNonSpeculative);
- // Read uniq reg into ABI return value register (r0)
- 0x9e: rduniq({{ R0 = Runiq; }});
- // Write uniq reg with value from ABI arg register (r16)
- 0x9f: wruniq({{ Runiq = R16; }});
- }
- }
-#endif
-
-#if FULL_SYSTEM
- format HwLoadStore {
- 0x1b: decode HW_LDST_QUAD {
- 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
- 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
- }
-
- 0x1f: decode HW_LDST_COND {
- 0: decode HW_LDST_QUAD {
- 0: hw_st({{ EA = (Rb + disp) & ~3; }},
- {{ Mem.ul = Ra<31:0>; }}, L);
- 1: hw_st({{ EA = (Rb + disp) & ~7; }},
- {{ Mem.uq = Ra.uq; }}, Q);
- }
-
- 1: FailUnimpl::hw_st_cond();
- }
- }
-
- format HwMoveIPR {
- 0x19: hw_mfpr({{
- // this instruction is only valid in PAL mode
- if (!xc->inPalMode()) {
- fault = Unimplemented_Opcode_Fault;
- }
- else {
- Ra = xc->readIpr(ipr_index, fault);
- }
- }});
- 0x1d: hw_mtpr({{
- // this instruction is only valid in PAL mode
- if (!xc->inPalMode()) {
- fault = Unimplemented_Opcode_Fault;
- }
- else {
- xc->setIpr(ipr_index, Ra);
- if (traceData) { traceData->setData(Ra); }
- }
- }});
- }
-
- format BasicOperate {
- 0x1e: hw_rei({{ xc->hwrei(); }}, IsSerializing);
-
- // M5 special opcodes use the reserved 0x01 opcode space
- 0x01: decode M5FUNC {
- 0x00: arm({{
- AlphaPseudo::arm(xc->xcBase());
- }}, IsNonSpeculative);
- 0x01: quiesce({{
- AlphaPseudo::quiesce(xc->xcBase());
- }}, IsNonSpeculative);
- 0x10: ivlb({{
- AlphaPseudo::ivlb(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x11: ivle({{
- AlphaPseudo::ivle(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x20: m5exit_old({{
- AlphaPseudo::m5exit_old(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x21: m5exit({{
- AlphaPseudo::m5exit(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
- 0x40: resetstats({{
- AlphaPseudo::resetstats(xc->xcBase());
- }}, IsNonSpeculative);
- 0x41: dumpstats({{
- AlphaPseudo::dumpstats(xc->xcBase());
- }}, IsNonSpeculative);
- 0x42: dumpresetstats({{
- AlphaPseudo::dumpresetstats(xc->xcBase());
- }}, IsNonSpeculative);
- 0x43: m5checkpoint({{
- AlphaPseudo::m5checkpoint(xc->xcBase());
- }}, IsNonSpeculative);
- 0x50: m5readfile({{
- AlphaPseudo::readfile(xc->xcBase());
- }}, IsNonSpeculative);
- 0x51: m5break({{
- AlphaPseudo::debugbreak(xc->xcBase());
- }}, IsNonSpeculative);
- 0x52: m5switchcpu({{
- AlphaPseudo::switchcpu(xc->xcBase());
- }}, IsNonSpeculative);
- 0x53: m5addsymbol({{
- AlphaPseudo::addsymbol(xc->xcBase());
- }}, IsNonSpeculative);
-
- }
- }
-#endif
-}
diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh
index 2570d12f0..a6e34acbb 100644
--- a/arch/alpha/isa_traits.hh
+++ b/arch/alpha/isa_traits.hh
@@ -29,10 +29,14 @@
#ifndef __ARCH_ALPHA_ISA_TRAITS_HH__
#define __ARCH_ALPHA_ISA_TRAITS_HH__
-#include "arch/alpha/faults.hh"
+namespace LittleEndianGuest {}
+using namespace LittleEndianGuest;
+
+//#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;
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index 8f4c6bce7..bcef77ddf 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -82,27 +82,34 @@ tokens = reserved + (
# ( ) [ ] { } < > , ; : :: *
'LPAREN', 'RPAREN',
-# not used any more... commented out to suppress PLY warning
-# 'LBRACKET', 'RBRACKET',
+ 'LBRACKET', 'RBRACKET',
'LBRACE', 'RBRACE',
- 'LESS', 'GREATER',
+ 'LESS', 'GREATER', 'EQUALS',
'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
'ASTERISK',
# C preprocessor directives
'CPPDIRECTIVE'
+
+# The following are matched but never returned. commented out to
+# suppress PLY warning
+ # newfile directive
+# 'NEWFILE',
+
+ # endfile directive
+# 'ENDFILE'
)
# Regular expressions for token matching
t_LPAREN = r'\('
t_RPAREN = r'\)'
-# not used any more... commented out to suppress PLY warning
-# t_LBRACKET = r'\['
-# t_RBRACKET = r'\]'
+t_LBRACKET = r'\['
+t_RBRACKET = r'\]'
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LESS = r'\<'
t_GREATER = r'\>'
+t_EQUALS = r'='
t_COMMA = r','
t_SEMI = r';'
t_COLON = r':'
@@ -149,10 +156,20 @@ def t_CODELIT(t):
return t
def t_CPPDIRECTIVE(t):
- r'^\#.*\n'
+ r'^\#[^\#].*\n'
t.lineno += t.value.count('\n')
return t
+def t_NEWFILE(t):
+ r'^\#\#newfile\s+"[\w/.-]*"'
+ global fileNameStack
+ fileNameStack.append((t.value[11:-1], t.lineno))
+ t.lineno = 0
+
+def t_ENDFILE(t):
+ r'^\#\#endfile'
+ (filename, t.lineno) = fileNameStack.pop()
+
#
# The functions t_NEWLINE, t_ignore, and t_error are
# special for the lex module.
@@ -303,25 +320,27 @@ def p_global_let(t):
# widths (stored in operandTypeMap).
def p_def_operand_types(t):
'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
- s = 'global operandTypeMap; operandTypeMap = {' + t[3] + '}'
try:
- exec s
+ userDict = eval('{' + t[3] + '}')
except Exception, exc:
error(t.lineno(1),
'error: %s in def operand_types block "%s".' % (exc, t[3]))
+ buildOperandTypeMap(userDict, t.lineno(1))
t[0] = GenCode() # contributes nothing to the output C++ file
# Define the mapping from operand names to operand classes and other
-# traits. Stored in operandTraitsMap.
+# traits. Stored in operandNameMap.
def p_def_operands(t):
'def_operands : DEF OPERANDS CODELIT SEMI'
- s = 'global operandTraitsMap; operandTraitsMap = {' + t[3] + '}'
+ if not globals().has_key('operandTypeMap'):
+ error(t.lineno(1),
+ 'error: operand types must be defined before operands')
try:
- exec s
+ userDict = eval('{' + t[3] + '}')
except Exception, exc:
error(t.lineno(1),
'error: %s in def operands block "%s".' % (exc, t[3]))
- defineDerivedOperandVars()
+ buildOperandNameMap(userDict, t.lineno(1))
t[0] = GenCode() # contributes nothing to the output C++ file
# A bitfield definition looks like:
@@ -369,32 +388,66 @@ def p_def_format(t):
t[0] = GenCode()
# The formal parameter list for an instruction format is a possibly
-# empty list of comma-separated parameters.
+# empty list of comma-separated parameters. Positional (standard,
+# non-keyword) parameters must come first, followed by keyword
+# parameters, followed by a '*foo' parameter that gets excess
+# positional arguments (as in Python). Each of these three parameter
+# categories is optional.
+#
+# Note that we do not support the '**foo' parameter for collecting
+# otherwise undefined keyword args. Otherwise the parameter list is
+# (I believe) identical to what is supported in Python.
+#
+# The param list generates a tuple, where the first element is a list of
+# the positional params and the second element is a dict containing the
+# keyword params.
def p_param_list_0(t):
- 'param_list : empty'
- t[0] = [ ]
+ 'param_list : positional_param_list COMMA nonpositional_param_list'
+ t[0] = t[1] + t[3]
def p_param_list_1(t):
- 'param_list : param'
+ '''param_list : positional_param_list
+ | nonpositional_param_list'''
+ t[0] = t[1]
+
+def p_positional_param_list_0(t):
+ 'positional_param_list : empty'
+ t[0] = []
+
+def p_positional_param_list_1(t):
+ 'positional_param_list : ID'
t[0] = [t[1]]
-def p_param_list_2(t):
- 'param_list : param_list COMMA param'
- t[0] = t[1]
- t[0].append(t[3])
+def p_positional_param_list_2(t):
+ 'positional_param_list : positional_param_list COMMA ID'
+ t[0] = t[1] + [t[3]]
+
+def p_nonpositional_param_list_0(t):
+ 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
+ t[0] = t[1] + t[3]
-# Each formal parameter is either an identifier or an identifier
-# preceded by an asterisk. As in Python, the latter (if present) gets
-# a tuple containing all the excess positional arguments, allowing
-# varargs functions.
-def p_param_0(t):
- 'param : ID'
+def p_nonpositional_param_list_1(t):
+ '''nonpositional_param_list : keyword_param_list
+ | excess_args_param'''
t[0] = t[1]
-def p_param_1(t):
- 'param : ASTERISK ID'
- # just concatenate them: '*ID'
- t[0] = t[1] + t[2]
+def p_keyword_param_list_0(t):
+ 'keyword_param_list : keyword_param'
+ t[0] = [t[1]]
+
+def p_keyword_param_list_1(t):
+ 'keyword_param_list : keyword_param_list COMMA keyword_param'
+ t[0] = t[1] + [t[3]]
+
+def p_keyword_param(t):
+ 'keyword_param : ID EQUALS expr'
+ t[0] = t[1] + ' = ' + t[3].__repr__()
+
+def p_excess_args_param(t):
+ 'excess_args_param : ASTERISK ID'
+ # Just concatenate them: '*ID'. Wrap in list to be consistent
+ # with positional_param_list and keyword_param_list.
+ t[0] = [t[1] + t[2]]
# End of format definition-related rules.
##############
@@ -559,25 +612,78 @@ def p_inst_1(t):
codeObj.prepend_all(comment)
t[0] = codeObj
+# The arg list generates a tuple, where the first element is a list of
+# the positional args and the second element is a dict containing the
+# keyword args.
def p_arg_list_0(t):
- 'arg_list : empty'
- t[0] = [ ]
+ 'arg_list : positional_arg_list COMMA keyword_arg_list'
+ t[0] = ( t[1], t[3] )
def p_arg_list_1(t):
- 'arg_list : arg'
- t[0] = [t[1]]
+ 'arg_list : positional_arg_list'
+ t[0] = ( t[1], {} )
def p_arg_list_2(t):
- 'arg_list : arg_list COMMA arg'
+ 'arg_list : keyword_arg_list'
+ t[0] = ( [], t[1] )
+
+def p_positional_arg_list_0(t):
+ 'positional_arg_list : empty'
+ t[0] = []
+
+def p_positional_arg_list_1(t):
+ 'positional_arg_list : expr'
+ t[0] = [t[1]]
+
+def p_positional_arg_list_2(t):
+ 'positional_arg_list : positional_arg_list COMMA expr'
+ t[0] = t[1] + [t[3]]
+
+def p_keyword_arg_list_0(t):
+ 'keyword_arg_list : keyword_arg'
t[0] = t[1]
- t[0].append(t[3])
-def p_arg(t):
- '''arg : ID
- | INTLIT
- | STRLIT
- | CODELIT'''
+def p_keyword_arg_list_1(t):
+ 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
t[0] = t[1]
+ t[0].update(t[3])
+
+def p_keyword_arg(t):
+ 'keyword_arg : ID EQUALS expr'
+ t[0] = { t[1] : t[3] }
+
+#
+# Basic expressions. These constitute the argument values of
+# "function calls" (i.e. instruction definitions in the decode block)
+# and default values for formal parameters of format functions.
+#
+# Right now, these are either strings, integers, or (recursively)
+# lists of exprs (using Python square-bracket list syntax). Note that
+# bare identifiers are trated as string constants here (since there
+# isn't really a variable namespace to refer to).
+#
+def p_expr_0(t):
+ '''expr : ID
+ | INTLIT
+ | STRLIT
+ | CODELIT'''
+ t[0] = t[1]
+
+def p_expr_1(t):
+ '''expr : LBRACKET list_expr RBRACKET'''
+ t[0] = t[2]
+
+def p_list_expr_0(t):
+ 'list_expr : expr'
+ t[0] = [t[1]]
+
+def p_list_expr_1(t):
+ 'list_expr : list_expr COMMA expr'
+ t[0] = t[1] + [t[3]]
+
+def p_list_expr_2(t):
+ 'list_expr : empty'
+ t[0] = []
#
# Empty production... use in other rules for readability.
@@ -739,6 +845,19 @@ class GenCode:
# a defineInst() method that generates the code for an instruction
# definition.
+exportContextSymbols = ('InstObjParams', 'CodeBlock',
+ 'makeList', 're', 'string')
+
+exportContext = {}
+
+def updateExportContext():
+ exportContext.update(exportDict(*exportContextSymbols))
+ exportContext.update(templateMap)
+
+def exportDict(*symNames):
+ return dict([(s, eval(s)) for s in symNames])
+
+
class Format:
def __init__(self, id, params, code):
# constructor: just save away arguments
@@ -761,7 +880,7 @@ class Format:
context.update(exportContext)
context.update({ 'name': name, 'Name': string.capitalize(name) })
try:
- vars = self.func(self.user_code, context, *args)
+ vars = self.func(self.user_code, context, *args[0], **args[1])
except Exception, exc:
error(lineno, 'error defining "%s": %s.' % (name, exc))
for k in vars.keys():
@@ -823,7 +942,7 @@ defaultStack = Stack( None )
# Used to make nested code blocks look pretty.
#
def indent(s):
- return re.sub(r'(?m)^(?!\#)', ' ', s)
+ return re.sub(r'(?m)^(?!#)', ' ', s)
#
# Munge a somewhat arbitrarily formatted piece of Python code
@@ -850,12 +969,21 @@ def fixPythonIndentation(s):
return s
# Error handler. Just call exit. Output formatted to work under
-# Emacs compile-mode.
+# Emacs compile-mode. This function should be called when errors due
+# to user input are detected (as opposed to parser bugs).
def error(lineno, string):
- sys.exit("%s:%d: %s" % (input_filename, lineno, string))
+ spaces = ""
+ for (filename, line) in fileNameStack[0:-1]:
+ print spaces + "In file included from " + filename
+ spaces += " "
+ # Uncomment the following line to get a Python stack backtrace for
+ # these errors too. Can be handy when trying to debug the parser.
+ # traceback.print_exc()
+ sys.exit(spaces + "%s:%d: %s" % (fileNameStack[-1][0], lineno, string))
# Like error(), but include a Python stack backtrace (for processing
-# Python exceptions).
+# Python exceptions). This function should be called for errors that
+# appear to be bugs in the parser itself.
def error_bt(lineno, string):
traceback.print_exc()
print >> sys.stderr, "%s:%d: %s" % (input_filename, lineno, string)
@@ -947,74 +1075,93 @@ class Template:
#
#####################################################################
-# Force the argument to be a list
-def makeList(list_or_item):
- if not list_or_item:
+# Force the argument to be a list. Useful for flags, where a caller
+# can specify a singleton flag or a list of flags. Also usful for
+# converting tuples to lists so they can be modified.
+def makeList(arg):
+ if isinstance(arg, list):
+ return arg
+ elif isinstance(arg, tuple):
+ return list(arg)
+ elif not arg:
return []
- elif type(list_or_item) == ListType:
- return list_or_item
else:
- return [ list_or_item ]
-
-# generate operandSizeMap based on provided operandTypeMap:
-# basically generate equiv. C++ type and make is_signed flag
-def buildOperandSizeMap():
- global operandSizeMap
- operandSizeMap = {}
- for ext in operandTypeMap.keys():
- (desc, size) = operandTypeMap[ext]
+ return [ arg ]
+
+# Generate operandTypeMap from the user's 'def operand_types'
+# statement.
+def buildOperandTypeMap(userDict, lineno):
+ global operandTypeMap
+ operandTypeMap = {}
+ for (ext, (desc, size)) in userDict.iteritems():
if desc == 'signed int':
- type = 'int%d_t' % size
+ ctype = 'int%d_t' % size
is_signed = 1
elif desc == 'unsigned int':
- type = 'uint%d_t' % size
+ ctype = 'uint%d_t' % size
is_signed = 0
elif desc == 'float':
is_signed = 1 # shouldn't really matter
if size == 32:
- type = 'float'
+ ctype = 'float'
elif size == 64:
- type = 'double'
- if type == '':
- error(0, 'Unrecognized type description "%s" in operandTypeMap')
- operandSizeMap[ext] = (size, type, is_signed)
+ ctype = 'double'
+ if ctype == '':
+ error(0, 'Unrecognized type description "%s" in userDict')
+ operandTypeMap[ext] = (size, ctype, is_signed)
#
-# Base class for operand traits. An instance of this class (or actually
-# a class derived from this one) encapsulates the traits of a particular
-# operand type (e.g., "32-bit integer register").
#
-class OperandTraits:
- def __init__(self, dflt_ext, reg_spec, flags, sort_pri):
- # Force construction of operandSizeMap from operandTypeMap
- # if it hasn't happened yet
- if not globals().has_key('operandSizeMap'):
- buildOperandSizeMap()
- self.dflt_ext = dflt_ext
- (self.dflt_size, self.dflt_type, self.dflt_is_signed) = \
- operandSizeMap[dflt_ext]
- self.reg_spec = reg_spec
- # Canonical flag structure is a triple of lists, where each list
- # indicates the set of flags implied by this operand always, when
- # used as a source, and when used as a dest, respectively.
- # For simplicity this can be initialized using a variety of fairly
- # obvious shortcuts; we convert these to canonical form here.
- if not flags:
- # no flags specified (e.g., 'None')
- self.flags = ( [], [], [] )
- elif type(flags) == StringType:
- # a single flag: assumed to be unconditional
- self.flags = ( [ flags ], [], [] )
- elif type(flags) == ListType:
- # a list of flags: also assumed to be unconditional
- self.flags = ( flags, [], [] )
- elif type(flags) == TupleType:
- # it's a tuple: it should be a triple,
- # but each item could be a single string or a list
- (uncond_flags, src_flags, dest_flags) = flags
- self.flags = (makeList(uncond_flags),
- makeList(src_flags), makeList(dest_flags))
- self.sort_pri = sort_pri
+#
+# Base class for operand descriptors. An instance of this class (or
+# actually a class derived from this one) represents a specific
+# operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
+# derived classes encapsulates the traits of a particular operand type
+# (e.g., "32-bit integer register").
+#
+class Operand(object):
+ def __init__(self, full_name, ext, is_src, is_dest):
+ self.full_name = full_name
+ self.ext = ext
+ self.is_src = is_src
+ self.is_dest = is_dest
+ # The 'effective extension' (eff_ext) is either the actual
+ # extension, if one was explicitly provided, or the default.
+ if ext:
+ self.eff_ext = ext
+ else:
+ self.eff_ext = self.dflt_ext
+
+ (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
+
+ # note that mem_acc_size is undefined for non-mem operands...
+ # 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
+ # register index enumeration that hasn't been performed yet at the
+ # time of __init__().
+ def finalize(self):
+ self.flags = self.getFlags()
+ self.constructor = self.makeConstructor()
+ self.op_decl = self.makeDecl()
+
+ 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
@@ -1031,234 +1178,239 @@ class OperandTraits:
def isControlReg(self):
return 0
- def getFlags(self, op_desc):
+ def getFlags(self):
# note the empty slice '[:]' gives us a copy of self.flags[0]
# instead of a reference to it
my_flags = self.flags[0][:]
- if op_desc.is_src:
+ if self.is_src:
my_flags += self.flags[1]
- if op_desc.is_dest:
+ if self.is_dest:
my_flags += self.flags[2]
return my_flags
- def makeDecl(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeDecl(self):
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
- return type + ' ' + op_desc.munged_name + ' = 0;\n';
+ return self.ctype + ' ' + self.base_name + ' = 0;\n';
-class IntRegOperandTraits(OperandTraits):
+class IntRegOperand(Operand):
def isReg(self):
return 1
def isIntReg(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
c = ''
- if op_desc.is_src:
+ if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ (self.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- if (type == 'float' or type == 'double'):
+ def makeRead(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read integer register as FP')
- if (size == self.dflt_size):
+ if (self.size == self.dflt_size):
return '%s = xc->readIntReg(this, %d);\n' % \
- (op_desc.munged_name, op_desc.src_reg_idx)
+ (self.base_name, self.src_reg_idx)
else:
return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
- (op_desc.munged_name, op_desc.src_reg_idx, size-1)
+ (self.base_name, self.src_reg_idx, self.size-1)
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- if (type == 'float' or type == 'double'):
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write integer register as FP')
- if (size != self.dflt_size and is_signed):
- final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name)
+ if (self.size != self.dflt_size and self.is_signed):
+ final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
else:
- final_val = op_desc.munged_name
+ final_val = self.base_name
wb = '''
{
%s final_val = %s;
xc->setIntReg(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
- }''' % (self.dflt_type, final_val, op_desc.dest_reg_idx)
+ }''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
return wb
-class FloatRegOperandTraits(OperandTraits):
+class FloatRegOperand(Operand):
def isReg(self):
return 1
def isFloatReg(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
c = ''
- if op_desc.is_src:
+ if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ (self.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeRead(self):
bit_select = 0
- if (type == 'float'):
+ if (self.ctype == 'float'):
func = 'readFloatRegSingle'
- elif (type == 'double'):
+ elif (self.ctype == 'double'):
func = 'readFloatRegDouble'
else:
func = 'readFloatRegInt'
- if (size != self.dflt_size):
+ if (self.size != self.dflt_size):
bit_select = 1
base = 'xc->%s(this, %d)' % \
- (func, op_desc.src_reg_idx)
+ (func, self.src_reg_idx)
if bit_select:
return '%s = bits(%s, %d, 0);\n' % \
- (op_desc.munged_name, base, size-1)
+ (self.base_name, base, self.size-1)
else:
- return '%s = %s;\n' % (op_desc.munged_name, base)
+ return '%s = %s;\n' % (self.base_name, base)
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- final_val = op_desc.munged_name
- if (type == 'float'):
+ def makeWrite(self):
+ final_val = self.base_name
+ final_ctype = self.ctype
+ if (self.ctype == 'float'):
func = 'setFloatRegSingle'
- elif (type == 'double'):
+ elif (self.ctype == 'double'):
func = 'setFloatRegDouble'
else:
func = 'setFloatRegInt'
- type = 'uint%d_t' % self.dflt_size
- if (size != self.dflt_size and is_signed):
- final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name)
+ final_ctype = 'uint%d_t' % self.dflt_size
+ if (self.size != self.dflt_size and self.is_signed):
+ final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
wb = '''
{
%s final_val = %s;
xc->%s(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
- }''' % (type, final_val, func, op_desc.dest_reg_idx)
+ }''' % (final_ctype, final_val, func, self.dest_reg_idx)
return wb
-class ControlRegOperandTraits(OperandTraits):
+class ControlRegOperand(Operand):
def isReg(self):
return 1
def isControlReg(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
c = ''
- if op_desc.is_src:
+ if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ (self.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeRead(self):
bit_select = 0
- if (type == 'float' or type == 'double'):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read control register as FP')
base = 'xc->read%s()' % self.reg_spec
- if size == self.dflt_size:
- return '%s = %s;\n' % (op_desc.munged_name, base)
+ if self.size == self.dflt_size:
+ return '%s = %s;\n' % (self.base_name, base)
else:
return '%s = bits(%s, %d, 0);\n' % \
- (op_desc.munged_name, base, size-1)
+ (self.base_name, base, self.size-1)
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- if (type == 'float' or type == 'double'):
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write control register as FP')
- wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.munged_name)
+ wb = 'xc->set%s(%s);\n' % (self.reg_spec, self.base_name)
wb += 'if (traceData) { traceData->setData(%s); }' % \
- op_desc.munged_name
+ self.base_name
return wb
-class MemOperandTraits(OperandTraits):
+class MemOperand(Operand):
def isMem(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
return ''
- def makeDecl(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeDecl(self):
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
# Declare memory data variable.
- c = '%s %s = 0;\n' % (type, op_desc.munged_name)
- # Declare var to hold memory access flags.
- c += 'unsigned %s_flags = memAccessFlags;\n' % op_desc.base_name
- # If this operand is a dest (i.e., it's a store operation),
- # then we need to declare a variable for the write result code
- # as well.
- if op_desc.is_dest:
- c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name
+ c = '%s %s = 0;\n' % (self.ctype, self.base_name)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- eff_type = 'uint%d_t' % size
- return 'fault = xc->read(EA, (%s&)%s, %s_flags);\n' \
- % (eff_type, op_desc.munged_name, op_desc.base_name)
-
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- eff_type = 'uint%d_t' % size
- wb = 'fault = xc->write((%s&)%s, EA, %s_flags, &%s_write_result);\n' \
- % (eff_type, op_desc.munged_name, op_desc.base_name,
- op_desc.base_name)
- wb += 'if (traceData) { traceData->setData(%s); }' % \
- op_desc.munged_name
- return wb
-
-class NPCOperandTraits(OperandTraits):
- def makeConstructor(self, op_desc):
+ def makeRead(self):
return ''
- def makeRead(self, op_desc):
- return '%s = xc->readPC() + 4;\n' % op_desc.munged_name
-
- def makeWrite(self, op_desc):
- return 'xc->setNextPC(%s);\n' % op_desc.munged_name
-
-
-exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
- 'ControlRegOperandTraits', 'MemOperandTraits',
- 'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
- 're', 'string')
+ def makeWrite(self):
+ return ''
-exportContext = {}
+ # Return the memory access size *in bits*, suitable for
+ # forming a type via "uint%d_t". Divide by 8 if you want bytes.
+ def makeAccSize(self):
+ return self.size
-def updateExportContext():
- exportContext.update(exportDict(*exportContextSymbols))
- exportContext.update(templateMap)
+class NPCOperand(Operand):
+ def makeConstructor(self):
+ return ''
+ def makeRead(self):
+ return '%s = xc->readPC() + 4;\n' % self.base_name
-def exportDict(*symNames):
- return dict([(s, eval(s)) for s in symNames])
+ def makeWrite(self):
+ return 'xc->setNextPC(%s);\n' % self.base_name
-#
-# Define operand variables that get derived from the basic declaration
-# of ISA-specific operands in operandTraitsMap. This function must be
-# called by the ISA description file explicitly after defining
-# operandTraitsMap (in a 'let' block).
-#
-def defineDerivedOperandVars():
- global operands
- operands = operandTraitsMap.keys()
+def buildOperandNameMap(userDict, lineno):
+ global operandNameMap
+ operandNameMap = {}
+ for (op_name, val) in userDict.iteritems():
+ (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val
+ (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
+ # Canonical flag structure is a triple of lists, where each list
+ # indicates the set of flags implied by this operand always, when
+ # used as a source, and when used as a dest, respectively.
+ # For simplicity this can be initialized using a variety of fairly
+ # obvious shortcuts; we convert these to canonical form here.
+ if not flags:
+ # no flags specified (e.g., 'None')
+ flags = ( [], [], [] )
+ elif isinstance(flags, str):
+ # a single flag: assumed to be unconditional
+ flags = ( [ flags ], [], [] )
+ elif isinstance(flags, list):
+ # a list of flags: also assumed to be unconditional
+ flags = ( flags, [], [] )
+ elif isinstance(flags, tuple):
+ # it's a tuple: it should be a triple,
+ # but each item could be a single string or a list
+ (uncond_flags, src_flags, dest_flags) = flags
+ flags = (makeList(uncond_flags),
+ makeList(src_flags), makeList(dest_flags))
+ # Accumulate attributes of new operand class in tmp_dict
+ tmp_dict = {}
+ for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
+ 'dflt_size', 'dflt_ctype', 'dflt_is_signed'):
+ tmp_dict[attr] = eval(attr)
+ tmp_dict['base_name'] = op_name
+ # New class name will be e.g. "IntReg_Ra"
+ cls_name = base_cls_name + '_' + op_name
+ # Evaluate string arg to get class object. Note that the
+ # actual base class for "IntReg" is "IntRegOperand", i.e. we
+ # have to append "Operand".
+ try:
+ base_cls = eval(base_cls_name + 'Operand')
+ except NameError:
+ error(lineno,
+ 'error: unknown operand base class "%s"' % base_cls_name)
+ # The following statement creates a new class called
+ # <cls_name> as a subclass of <base_cls> with the attributes
+ # in tmp_dict, just as if we evaluated a class declaration.
+ operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
+
+ # Define operand variables.
+ operands = userDict.keys()
operandsREString = (r'''
(?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
@@ -1280,52 +1432,72 @@ def defineDerivedOperandVars():
operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
-#
-# Operand descriptor class. An instance of this class represents
-# a specific operand for a code block.
-#
-class OperandDescriptor:
- def __init__(self, full_name, base_name, ext, is_src, is_dest):
- self.full_name = full_name
- self.base_name = base_name
- self.ext = ext
- self.is_src = is_src
- self.is_dest = is_dest
- self.traits = operandTraitsMap[base_name]
- # The 'effective extension' (eff_ext) is either the actual
- # extension, if one was explicitly provided, or the default.
- # The 'munged name' replaces the '.' between the base and
- # extension (if any) with a '_' to make a legal C++ variable name.
- if ext:
- self.eff_ext = ext
- self.munged_name = base_name + '_' + ext
- else:
- self.eff_ext = self.traits.dflt_ext
- self.munged_name = base_name
-
- # Finalize additional fields (primarily code fields). This step
- # is done separately since some of these fields may depend on the
- # register index enumeration that hasn't been performed yet at the
- # time of __init__().
- def finalize(self):
- self.flags = self.traits.getFlags(self)
- self.constructor = self.traits.makeConstructor(self)
- self.op_decl = self.traits.makeDecl(self)
-
- if self.is_src:
- self.op_rd = self.traits.makeRead(self)
- else:
- self.op_rd = ''
-
- if self.is_dest:
- self.op_wb = self.traits.makeWrite(self)
- else:
- self.op_wb = ''
+class OperandList:
-class OperandDescriptorList:
- def __init__(self):
+ # Find all the operands in the given code block. Returns an operand
+ # descriptor list (instance of class OperandList).
+ def __init__(self, code):
self.items = []
self.bases = {}
+ # delete comments so we don't match on reg specifiers inside
+ code = commentRE.sub('', code)
+ # search for operands
+ next_pos = 0
+ while 1:
+ match = operandsRE.search(code, next_pos)
+ if not match:
+ # no more matches: we're done
+ break
+ op = match.groups()
+ # regexp groups are operand full name, base, and extension
+ (op_full, op_base, op_ext) = op
+ # if the token following the operand is an assignment, this is
+ # a destination (LHS), else it's a source (RHS)
+ is_dest = (assignRE.match(code, match.end()) != None)
+ is_src = not is_dest
+ # see if we've already seen this one
+ op_desc = self.find_base(op_base)
+ if op_desc:
+ if op_desc.ext != op_ext:
+ error(0, 'Inconsistent extensions for operand %s' % \
+ op_base)
+ op_desc.is_src = op_desc.is_src or is_src
+ op_desc.is_dest = op_desc.is_dest or is_dest
+ else:
+ # new operand: create new descriptor
+ op_desc = operandNameMap[op_base](op_full, op_ext,
+ is_src, is_dest)
+ self.append(op_desc)
+ # start next search after end of current match
+ next_pos = match.end()
+ self.sort()
+ # enumerate source & dest register operands... used in building
+ # constructor later
+ self.numSrcRegs = 0
+ self.numDestRegs = 0
+ self.numFPDestRegs = 0
+ self.numIntDestRegs = 0
+ self.memOperand = None
+ for op_desc in self.items:
+ if op_desc.isReg():
+ if op_desc.is_src:
+ op_desc.src_reg_idx = self.numSrcRegs
+ self.numSrcRegs += 1
+ if op_desc.is_dest:
+ op_desc.dest_reg_idx = self.numDestRegs
+ self.numDestRegs += 1
+ if op_desc.isFloatReg():
+ self.numFPDestRegs += 1
+ elif op_desc.isIntReg():
+ self.numIntDestRegs += 1
+ elif op_desc.isMem():
+ if self.memOperand:
+ error(0, "Code block has more than one memory operand.")
+ self.memOperand = op_desc
+ # now make a final pass to finalize op_desc fields that may depend
+ # on the register enumeration
+ for op_desc in self.items:
+ op_desc.finalize()
def __len__(self):
return len(self.items)
@@ -1370,7 +1542,7 @@ class OperandDescriptorList:
return self.__internalConcatAttrs(attr_name, filter, [])
def sort(self):
- self.items.sort(lambda a, b: a.traits.sort_pri - b.traits.sort_pri)
+ self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
# Regular expression object to match C++ comments
# (used in findOperands())
@@ -1380,73 +1552,11 @@ commentRE = re.compile(r'//.*\n')
# (used in findOperands())
assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
-#
-# Find all the operands in the given code block. Returns an operand
-# descriptor list (instance of class OperandDescriptorList).
-#
-def findOperands(code):
- operands = OperandDescriptorList()
- # delete comments so we don't accidentally match on reg specifiers inside
- code = commentRE.sub('', code)
- # search for operands
- next_pos = 0
- while 1:
- match = operandsRE.search(code, next_pos)
- if not match:
- # no more matches: we're done
- break
- op = match.groups()
- # regexp groups are operand full name, base, and extension
- (op_full, op_base, op_ext) = op
- # if the token following the operand is an assignment, this is
- # a destination (LHS), else it's a source (RHS)
- is_dest = (assignRE.match(code, match.end()) != None)
- is_src = not is_dest
- # see if we've already seen this one
- op_desc = operands.find_base(op_base)
- if op_desc:
- if op_desc.ext != op_ext:
- error(0, 'Inconsistent extensions for operand %s' % op_base)
- op_desc.is_src = op_desc.is_src or is_src
- op_desc.is_dest = op_desc.is_dest or is_dest
- else:
- # new operand: create new descriptor
- op_desc = OperandDescriptor(op_full, op_base, op_ext,
- is_src, is_dest)
- operands.append(op_desc)
- # start next search after end of current match
- next_pos = match.end()
- operands.sort()
- # enumerate source & dest register operands... used in building
- # constructor later
- srcRegs = 0
- destRegs = 0
- operands.numFPDestRegs = 0
- operands.numIntDestRegs = 0
- for op_desc in operands:
- if op_desc.traits.isReg():
- if op_desc.is_src:
- op_desc.src_reg_idx = srcRegs
- srcRegs += 1
- if op_desc.is_dest:
- op_desc.dest_reg_idx = destRegs
- destRegs += 1
- if op_desc.traits.isFloatReg():
- operands.numFPDestRegs += 1
- elif op_desc.traits.isIntReg():
- operands.numIntDestRegs += 1
- operands.numSrcRegs = srcRegs
- operands.numDestRegs = destRegs
- # now make a final pass to finalize op_desc fields that may depend
- # on the register enumeration
- for op_desc in operands:
- op_desc.finalize()
- return operands
-
# Munge operand names in code string to make legal C++ variable names.
-# (Will match munged_name attribute of OperandDescriptor object.)
+# This means getting rid of the type extension if any.
+# (Will match base_name attribute of Operand object.)
def substMungedOpNames(code):
- return operandsWithExtRE.sub(r'\1_\2', code)
+ return operandsWithExtRE.sub(r'\1', code)
def joinLists(t):
return map(string.join, t)
@@ -1470,7 +1580,7 @@ def makeFlagConstructor(flag_list):
class CodeBlock:
def __init__(self, code):
self.orig_code = code
- self.operands = findOperands(code)
+ self.operands = OperandList(code)
self.code = substMungedOpNames(substBitOps(code))
self.constructor = self.operands.concatAttrStrings('constructor')
self.constructor += \
@@ -1484,22 +1594,23 @@ class CodeBlock:
self.op_decl = self.operands.concatAttrStrings('op_decl')
- is_mem = lambda op: op.traits.isMem()
- not_mem = lambda op: not op.traits.isMem()
+ 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')
- self.op_mem_rd = \
- self.operands.concatSomeAttrStrings(is_mem, 'op_rd')
- self.op_mem_wb = \
- self.operands.concatSomeAttrStrings(is_mem, 'op_wb')
- self.op_nonmem_rd = \
- self.operands.concatSomeAttrStrings(not_mem, 'op_rd')
- self.op_nonmem_wb = \
- self.operands.concatSomeAttrStrings(not_mem, 'op_wb')
self.flags = self.operands.concatAttrLists('flags')
+ 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
# later otherwise.
@@ -1601,6 +1712,30 @@ def update_if_needed(file, contents):
f.write(contents)
f.close()
+# This regular expression matches include directives
+includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
+ re.MULTILINE)
+
+def preprocess_isa_desc(isa_desc):
+ # Find any includes and include them
+ pos = 0
+ while 1:
+ m = includeRE.search(isa_desc, pos)
+ if not m:
+ break
+ filename = m.group('filename')
+ print 'Including file "%s"' % filename
+ try:
+ isa_desc = isa_desc[:m.start()] + \
+ '##newfile "' + filename + '"\n' + \
+ open(filename).read() + \
+ '##endfile\n' + \
+ isa_desc[m.end():]
+ except IOError:
+ error(0, 'Error including file "%s"' % (filename))
+ pos = m.start()
+ return isa_desc
+
#
# Read in and parse the ISA description.
#
@@ -1608,12 +1743,17 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path):
# set a global var for the input filename... used in error messages
global input_filename
input_filename = isa_desc_file
+ global fileNameStack
+ fileNameStack = [(input_filename, 1)]
# Suck the ISA description file in.
input = open(isa_desc_file)
isa_desc = input.read()
input.close()
+ # Perform Preprocessing
+ isa_desc = preprocess_isa_desc(isa_desc)
+
# Parse it.
(isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc)
diff --git a/arch/mips/SConscript b/arch/mips/SConscript
new file mode 100644
index 000000000..bd67c98e9
--- /dev/null
+++ b/arch/mips/SConscript
@@ -0,0 +1,81 @@
+# -*- 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.
+arch_base_sources = Split('''
+ arch/mips/decoder.cc
+ arch/mips/alpha_o3_exec.cc
+ arch/mips/fast_cpu_exec.cc
+ arch/mips/simple_cpu_exec.cc
+ arch/mips/full_cpu_exec.cc
+ arch/mips/faults.cc
+ arch/mips/isa_traits.cc
+ ''')
+
+# Full-system sources
+arch_full_system_sources = Split('''
+ arch/mips/alpha_memory.cc
+ arch/mips/arguments.cc
+ arch/mips/ev5.cc
+ arch/mips/osfpal.cc
+ arch/mips/stacktrace.cc
+ arch/mips/vtophys.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+arch_syscall_emulation_sources = Split('''
+ arch/mips/alpha_common_syscall_emul.cc
+ arch/mips/alpha_linux_process.cc
+ arch/mips/alpha_tru64_process.cc
+ ''')
+
+# Set up complete list of sources based on configuration.
+sources = arch_base_sources
+
+if env['FULL_SYSTEM']:
+ sources += arch_full_system_sources
+else:
+ sources += arch_syscall_emulation_sources
+
+for opt in env.ExportOptions:
+ env.ConfigFile(opt)
+
+Return('sources')
diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa
new file mode 100644
index 000000000..bead9c151
--- /dev/null
+++ b/arch/mips/isa/bitfields.isa
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+def bitfield OPCODE_HI <31:29>;
+def bitfield OPCODE_LO <28:26>;
+
+def bitfield FUNCTION_HI < 5: 3>;
+def bitfield FUNCTION_LO < 2: 0>;
+
+// Integer operate format
+def bitfield RT <20:16>;
+def bitfield RT_HI <20:19>;
+def bitfield RT_LO <18:16>;
+
+def bitfield RS <25:21>;
+def bitfield RS_MSB <25:25>;
+def bitfield RS_HI <25:24>;
+def bitfield RS_LO <23:21>;
+
+def bitfield RD <15:11>;
+
+def bitfield INTIMM <15: 0>; // integer immediate (literal)
+
+// Floating-point operate format
+def bitfield FMT <25:21>;
+def bitfield FT <20:16>;
+def bitfield FS <15:11>;
+def bitfield FD <10:6>;
+
+def bitfield MOVCI <16:16>;
+def bitfield MOVCF <16:16>;
+def bitfield SRL <21:21>;
+def bitfield SRLV < 6: 6>;
+def bitfield SA <10: 6>;
+
+// Interrupts
+def bitfield SC < 5: 5>;
+
+// Branch format
+def bitfield OFFSET <15: 0>; // displacement
+
+// Memory-format jumps
+def bitfield JMPTARG <25: 0>;
+def bitfield JMPHINT <10: 6>;
+
+def bitfield SYSCALLCODE <25: 6>;
+def bitfield TRAPCODE <15:13>;
+
+// M5 instructions
+def bitfield M5FUNC <7:0>;
diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa
new file mode 100644
index 000000000..6bb5bf4d8
--- /dev/null
+++ b/arch/mips/isa/decoder.isa
@@ -0,0 +1,902 @@
+////////////////////////////////////////////////////////////////////
+//
+// The actual MIPS32 ISA decoder
+// -----------------------------
+// The following instructions are specified in the MIPS32 ISA
+// Specification. Decoding closely follows the style specified
+// in the MIPS32 ISAthe specification document starting with Table
+// A-2 (document available @ www.mips.com)
+//
+//@todo: Distinguish "unknown/future" use insts from "reserved"
+// ones
+decode OPCODE_HI default Unknown::unknown() {
+
+ // Derived From ... Table A-2 MIPS32 ISA Manual
+ 0x0: decode OPCODE_LO default FailUnimpl::reserved(){
+
+ 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}});
+ }
+ }
+
+ 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."
+
+ 0x0: sll({{ 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);}});
+ }
+
+ 0x3: sra({{ Rd = Rt.sw >> SA; }});
+
+ 0x4: sllv({{ 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>);}});
+ }
+
+ 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();
+ }
+ }
+
+ 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; }});
+ }
+ }
+
+ 0x3: decode FUNCTION_LO {
+ format IntOp {
+ 0x0: mult({{
+ INT64 temp1 = Rs.sw * Rt.sw;
+ xc->miscRegs.hi->temp1<63:32>;
+ xc->miscRegs.lo->temp1<31:0>;
+ }});
+
+ 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;
+ }});
+
+ 0x2: div({{
+ xc->miscRegs.hi = Rs.sw % Rt.sw;
+ xc->miscRegs.lo = Rs.sw / Rt.sw;
+ }});
+
+ 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);}});
+ }
+ }
+
+ 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}});
+ }
+ }
+
+ 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); }});
+ }
+ }
+ }
+
+ 0x1: decode REGIMM_HI {
+ 0x0: decode REGIMM_LO {
+ format CondBranch {
+ 0x0: bltz({{ cond = (Rs.sw < 0); }});
+ 0x1: bgez({{ cond = (Rs.sw >= 0); }});
+
+ //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); }});
+ }
+ }
+
+ 0x2: decode REGIMM_LO {
+ format CondBranch {
+ 0x0: bltzal({{ cond = (Rs.sw < 0); }});
+ 0x1: bgezal({{ cond = (Rs.sw >= 0); }});
+
+ //MIPS obsolete instructions
+ 0x2: bltzall({{ cond = (Rs.sw < 0); }});
+ 0x3: bgezall({{ cond = (Rs.sw >= 0); }});
+ }
+ }
+
+ 0x3: decode REGIMM_LO {
+ format WarnUnimpl {
+ 0x7: synci();
+ }
+ }
+ }
+
+ format Jump {
+ 0x2: j();
+ 0x3: jal(IsCall);
+ }
+
+ format CondBranch {
+ 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(){
+ format IntOp {
+ 0x0: addi({{ Rt.sw = Rs.sw + INTIMM; }});
+ 0x1: addiu({{ Rt.uw = Rs.uw + INTIMM;}});
+ 0x2: slti({{ Rt.sw = ( Rs.sw < INTIMM ) ? 1 : 0 }});
+ 0x3: sltiu({{ Rt.uw = ( Rs.uw < INTIMM ) ? 1 : 0 }});
+ 0x4: andi({{ Rt.sw = Rs.sw & INTIMM;}});
+ 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 {
+
+ 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");
+
+ uint64_t reg_num = Rd.uw;
+
+ Rt = xc->miscRegs.cop0[reg_num];
+ }});
+
+ 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");
+
+ uint64_t reg_num = Rd.uw;
+
+ xc->miscRegs.cop0[reg_num] = Rt;
+ }});
+
+ 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({{
+ //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({{
+ //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 {
+
+ 0x0: decode SC {
+ format BasicOp {
+ 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: decode SC {
+ format BasicOp {
+ 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;
+ }});
+ }
+ }
+
+ 0xC: decode SC {
+ format BasicOp {
+ 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;
+ }});
+ }
+ }
+ }
+
+ 0xE: BasicOp::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 CondBranch {
+ 0x0: bc1f({{ cond = (xc->miscRegs.fpcr == 0); }});
+ 0x1: bc1t({{ cond = (xc->miscRegs.fpcr == 1); }});
+ }
+ }
+
+ 0x1: decode TF {
+ format CondBranch {
+ 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;}});
+ }
+ }
+
+ 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;
+ 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;
+ 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 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); }});
+ }
+ }
+
+ 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: 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 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({{
+ int rnd_mode = xc->miscRegs.fcsr;
+ Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD);
+ }});
+
+ 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({{
+ int rnd_mode = xc->miscRegs.fcsr;
+ Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG);
+ }});
+
+ 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;
+ }});
+
+ 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;
+ }});
+
+ 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>;
+ }});
+
+ 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 Float64Op {
+ 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}});
+ 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}});
+ }
+ }
+
+ }
+
+ 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 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();
+ 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; }});
+ }
+ }
+
+ 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: 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;
+ }});
+ }
+ }
+ }
+ }
+
+ //MIPS obsolete instructions
+ format CondBranch {
+ 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() {
+
+ //Table A-5 MIPS32 SPECIAL2 Encoding of Function Field
+ 0x4: decode FUNCTION_HI {
+
+ 0x0: decode FUNCTION_LO {
+ format IntOp {
+ 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({{
+ 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; }});
+
+ 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({{
+ 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({{
+ int cnt = 0;
+ int idx = 0;
+ while ( Rs.uw<idx>!= 1) {
+ cnt++;
+ idx--;
+ }
+
+ Rd.uw = cnt;
+ }});
+
+ 0x1: clo({{
+ int cnt = 0;
+ int idx = 0;
+ while ( Rs.uw<idx>!= 0) {
+ cnt++;
+ idx--;
+ }
+
+ Rd.uw = cnt;
+ }});
+ }
+ }
+
+ 0x7: decode FUNCTION_LO {
+ 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 {
+ format WarnUnimpl {
+ 0x1: ext();
+ 0x4: ins();
+ }
+ }
+
+ 0x1: decode FUNCTION_LO {
+ format WarnUnimpl {
+ 0x0: fork();
+ 0x1: yield();
+ }
+ }
+
+
+ //Table A-10 MIPS32 BSHFL Encoding of sa Field
+ 0x4: decode SA {
+
+ 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];}});
+ }
+ }
+ }
+
+ 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();
+ }
+
+ 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 WarnUnimpl {
+ 0x7: cache();
+ }
+
+ }
+
+ 0x6: decode OPCODE_LO default FailUnimpl::reserved() {
+ 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; }});
+ }
+ }
+
+ 0x7: decode OPCODE_LO default FailUnimpl::reserved() {
+ 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>; }});
+ }
+
+ }
+}
+
+
diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa
new file mode 100644
index 000000000..20ef49d82
--- /dev/null
+++ b/arch/mips/isa/formats.isa
@@ -0,0 +1,29 @@
+//Include the basic format
+//Templates from this format are used later
+##include "m5/arch/mips/isa/formats/basic.isa"
+
+//Include the integerOp and integerOpCc format
+##include "m5/arch/mips/isa/formats/int.isa"
+
+//Include the floatOp format
+##include "m5/arch/mips/isa/formats/fp.isa"
+
+//Include the mem format
+##include "m5/arch/mips/isa/formats/mem.isa"
+
+//Include the trap format
+##include "m5/arch/mips/isa/formats/trap.isa"
+
+//Include the branch format
+##include "m5/arch/mips/isa/formats/branch.isa"
+
+//Include the noop format
+##include "m5/arch/mips/isa/formats/noop.isa"
+
+
+//Include the noop format
+##include "m5/arch/mips/isa/formats/unimp.isa"
+
+//Include the 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
new file mode 100644
index 000000000..fc97c6ffa
--- /dev/null
+++ b/arch/mips/isa/formats/basic.isa
@@ -0,0 +1,65 @@
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ /// Constructor.
+ %(class_name)s(MachInst machInst);
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if(fault == No_Fault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// The most basic instruction format... used only for a few misc. insts
+def format BasicOp(code, *flags) {{
+ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
+ 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/branch.isa b/arch/mips/isa/formats/branch.isa
new file mode 100644
index 000000000..e9c790c53
--- /dev/null
+++ b/arch/mips/isa/formats/branch.isa
@@ -0,0 +1,259 @@
+// -*- 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 {{
+
+ /**
+ * 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 AlphaStaticInst
+ {
+ 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)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(BRDISP << 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 Alpha 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(BRDISP)
+ {
+ }
+
+ Addr branchTarget(ExecContext *xc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::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)
+ {
+ 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
+ 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 template JumpOrBranchDecode {{
+ return (RA == 31)
+ ? (StaticInst<AlphaISA> *)new %(class_name)s(machInst)
+ : (StaticInst<AlphaISA> *)new %(class_name)sAndLink(machInst);
+}};
+
+def format CondBranch(code) {{
+ code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\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)
+}};
+
+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 format UncondBranch(*flags) {{
+ flags += ('IsUncondControl', 'IsDirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+}};
+
+def format Jump(*flags) {{
+ flags += ('IsUncondControl', 'IsIndirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+}};
+
+
diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa
new file mode 100644
index 000000000..23fcbaa67
--- /dev/null
+++ b/arch/mips/isa/formats/fp.isa
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////
+//
+// Floating Point operate instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class FPOp : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ FPOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string FPOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+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
+ //is generated
+ bool useCc = ;
+ bool checkPriv = ;
+
+ //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;
+ if(useCc)
+ {
+ xc->regs.miscRegFile.ccrFields.iccFields.n = Rd & (1 << 63);
+ xc->regs.miscRegFile.ccrFields.iccFields.z = (Rd == 0);
+ xc->regs.miscRegFile.ccrFields.iccFields.v = ivValue;
+ xc->regs.miscRegFile.ccrFields.iccFields.c = icValue;
+ xc->regs.miscRegFile.ccrFields.xccFields.n = Rd & (1 << 31);
+ xc->regs.miscRegFile.ccrFields.xccFields.z = ((Rd & 0xFFFFFFFF) == 0);
+ xc->regs.miscRegFile.ccrFields.xccFields.v = xvValue;
+ xc->regs.miscRegFile.ccrFields.xccFields.c = xcValue;
+ }
+ return No_Fault;
+ }
+}};
+
+// Primary format for integer operate instructions:
+def format FloatOp(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 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', '')
+ if checkPriv:
+ code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;')
+ else:
+ code.replace('checkPriv;', '')
+ for (marker, value) in (('ivValue', ivValue), ('icValue', icValue),
+ ('xvValue', xvValue), ('xcValue', xcValue)):
+ 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 = IntegerExecute.subst(iop)
+}};
diff --git a/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa
new file mode 100644
index 000000000..521f3a130
--- /dev/null
+++ b/arch/mips/isa/formats/int.isa
@@ -0,0 +1,70 @@
+////////////////////////////////////////////////////////////////////
+//
+// Integer operate instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class IntOp : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ class IntImmOp : public MipsStaticInst
+ {
+ protected:
+ uint16_t imm;
+
+ /// Constructor
+ IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+output decoder {{
+ std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+
+ std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer immediate instruction\n";
+ }
+}};
+
+// Primary format for integer operate instructions:
+def format IntOp(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+
+ # Figure out if we are creating a IntImmOp or a IntOp
+ 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)
+
+ 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/mem.isa b/arch/mips/isa/formats/mem.isa
new file mode 100644
index 000000000..e3028eb7c
--- /dev/null
+++ b/arch/mips/isa/formats/mem.isa
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////
+//
+// Mem instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Mem : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Mem(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+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 Memory(code, ea_code = {{ EA = Rb + disp; }},*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;');
+}};
diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa
new file mode 100644
index 000000000..6d45ba9b6
--- /dev/null
+++ b/arch/mips/isa/formats/noop.isa
@@ -0,0 +1,134 @@
+////////////////////////////////////////////////////////////////////
+//
+// Noop instruction
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Noop : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Noop(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Noop::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+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;
+ }
+}};
+
+// 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)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
+
+output header {{
+ /**
+ * Static instruction class for no-ops. This is a leaf class.
+ */
+ class Nop : public AlphaStaticInst
+ {
+ /// Disassembly of original instruction.
+ const std::string originalDisassembly;
+
+ public:
+ /// Constructor
+ Nop(const std::string _originalDisassembly, MachInst _machInst)
+ : AlphaStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ flags[IsNop] = true;
+ }
+
+ ~Nop() { }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+output decoder {{
+ 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
+ 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;
+ }
+}};
+
+// integer & FP operate instructions use Rc as dest, so check for
+// Rc == 31 to detect nops
+def template OperateNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+
+// Like BasicOperate format, but generates NOP if RC/FC == 31
+def format BasicOperateWithNopCheck(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', 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/tlbop.isa b/arch/mips/isa/formats/tlbop.isa
new file mode 100644
index 000000000..f5e4076f2
--- /dev/null
+++ b/arch/mips/isa/formats/tlbop.isa
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////
+//
+// TlbOp instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class TlbOp : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ TlbOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string TlbOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+def template TlbOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ //Call into the trap handler with the appropriate fault
+ 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 TlbOp(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 = TlbOpExecute.subst(iop)
+}};
diff --git a/arch/mips/isa/formats/trap.isa b/arch/mips/isa/formats/trap.isa
new file mode 100644
index 000000000..78f8d87b0
--- /dev/null
+++ b/arch/mips/isa/formats/trap.isa
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////
+//
+// Trap instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Trap : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Trap(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Trap::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+def template TrapExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ //Call into the trap handler with the appropriate fault
+ 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 Trap(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 = TrapExecute.subst(iop)
+}};
diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa
new file mode 100644
index 000000000..767888157
--- /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 AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : AlphaStaticInst(_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 AlphaStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : AlphaStaticInst(_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 AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(MachInst _machInst)
+ : AlphaStaticInst("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/includes.isa b/arch/mips/isa/includes.isa
new file mode 100644
index 000000000..ff7cb7d1d
--- /dev/null
+++ b/arch/mips/isa/includes.isa
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "cpu/static_inst.hh"
+#include "traps.hh"
+#include "mem/mem_req.hh" // some constructors use MemReq flags
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+}};
+
+output exec {{
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+#ifdef FULL_SYSTEM
+//#include "arch/alpha/pseudo_inst.hh"
+#endif
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+}};
+
diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa
new file mode 100644
index 000000000..411e398b4
--- /dev/null
+++ b/arch/mips/isa/main.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.
+
+##include "m5/arch/mips/isa/includes.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// MipsISAInst namespace.
+//
+
+namespace MipsISA;
+
+//Include the bitfield definitions
+##include "m5/arch/mips/isa/bitfields.isa"
+
+//Include the operand_types and operand definitions
+##include "m5/arch/mips/isa/operands.isa"
+
+//Include the base class for mips instructions, and some support code
+##include "m5/arch/mips/isa/base.isa"
+
+//Include the definitions for the instruction formats
+##include "m5/arch/mips/isa/formats.isa"
+
+//Include the decoder definition
+##include "m5/arch/mips/isa/decoder.isa"
diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa
new file mode 100644
index 000000000..cf6f10e0b
--- /dev/null
+++ b/arch/mips/isa/operands.isa
@@ -0,0 +1,35 @@
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'shw' : ('signed int', 16),
+ 'uhw' : ('unsigned int', 16),
+ 'sw' : ('signed int', 32),
+ 'uw' : ('unsigned int', 32),
+ 'sd' : ('signed int', 64),
+ 'ud' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64),
+ 'qf' : ('float', 128)
+}};
+
+def operands {{
+ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1),
+ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2),
+ 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3),
+
+ 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
+ 'Sa': ('IntReg', 'uw', 'SA', 'IsInteger', 4),
+
+ 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1),
+ 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2),
+ 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3),
+
+ 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4)
+
+ #'NPC': ('NPC', 'uq', 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.cc b/arch/mips/isa_traits.cc
new file mode 100644
index 000000000..90a85feb6
--- /dev/null
+++ b/arch/mips/isa_traits.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/mips/isa_traits.hh"
+#include "cpu/static_inst.hh"
+#include "sim/serialize.hh"
+
+// Alpha UNOP (ldq_u r31,0(r0))
+// @todo: fix to MIPS specific
+const MachInst MipsISA::NoopMachInst = 0x2ffe0000;
+
+void
+MipsISA::RegFile::serialize(std::ostream &os)
+{
+ intRegFile.serialize(os);
+ floatRegFile.serialize(os);
+ miscRegs.serialize(os);
+ SERIALIZE_SCALAR(pc);
+ SERIALIZE_SCALAR(npc);
+}
+
+
+void
+MipsISA::RegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ intRegFile.unserialize(cp, section);
+ floatRegFile.unserialize(cp, section);
+ miscRegs.unserialize(cp, section);
+ UNSERIALIZE_SCALAR(pc);
+ UNSERIALIZE_SCALAR(npc);
+}
+
+#endif //FULL_SYSTEM
diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh
new file mode 100644
index 000000000..55e9c0dcb
--- /dev/null
+++ b/arch/mips/isa_traits.hh
@@ -0,0 +1,532 @@
+/*
+ * 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_MIPS_ISA_TRAITS_HH__
+#define __ARCH_MIPS_ISA_TRAITS_HH__
+
+//This makes sure the big endian versions of certain functions are used.
+namespace LittleEndianGuest {}
+using namespace LittleEndianGuest
+
+#include "arch/mips/faults.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+class FastCPU;
+class FullCPU;
+class Checkpoint;
+
+#define TARGET_MIPS
+
+template <class ISA> class StaticInst;
+template <class ISA> class StaticInstPtr;
+
+//namespace EV5
+//{
+// int DTB_ASN_ASN(uint64_t reg);
+// int ITB_ASN_ASN(uint64_t reg);
+//}
+
+class MipsISA
+{
+ public:
+
+ typedef uint32_t MachInst;
+ typedef uint64_t Addr;
+ typedef uint8_t RegIndex;
+
+ enum
+ {
+ MemoryEnd = 0xffffffffffffffffULL,
+
+ NumFloatRegs = 32,
+ NumMiscRegs = 32,
+
+ MaxRegsOfAnyType = 32,
+ // Static instruction parameters
+ MaxInstSrcRegs = 3,
+ MaxInstDestRegs = 2,
+
+ // Maximum trap level
+ MaxTL = 4
+
+ // semantically meaningful register indices
+ ZeroReg = 0, // architecturally meaningful
+ // the rest of these depend on the ABI
+ }
+ typedef uint64_t IntReg;
+
+ class IntRegFile
+ {
+ private:
+ //For right now, let's pretend the register file is static
+ IntReg regs[32];
+ public:
+ IntReg & operator [] (RegIndex index)
+ {
+ //Don't allow indexes outside of the 32 registers
+ index &= 0x1F
+ return regs[index];
+ }
+ };
+
+ void inline serialize(std::ostream & os)
+ {
+ SERIALIZE_ARRAY(regs, 32);
+ }
+
+ void inline unserialize(Checkpoint &*cp, const std::string &section)
+ {
+ UNSERIALIZE_ARRAY(regs, 32);
+ }
+
+ class FloatRegFile
+ {
+ private:
+ //By using the largest data type, we ensure everything
+ //is aligned correctly in memory
+ union
+ {
+ double double rawRegs[16];
+ uint64_t regDump[32];
+ };
+ class QuadRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ QuadRegs(FloatRegFile * p) : parent(p) {;}
+ double double & operator [] (RegIndex index)
+ {
+ //Quad floats are index by the single
+ //precision register the start on,
+ //and only 16 should be accessed
+ index = (index >> 2) & 0xF;
+ return parent->rawRegs[index];
+ }
+ };
+ class DoubleRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ DoubleRegs(FloatRegFile * p) : parent(p) {;}
+ double & operator [] (RegIndex index)
+ {
+ //Double floats are index by the single
+ //precision register the start on,
+ //and only 32 should be accessed
+ index = (index >> 1) & 0x1F
+ return ((double [])parent->rawRegs)[index];
+ }
+ }
+ class SingleRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ SingleRegs(FloatRegFile * p) : parent(p) {;}
+ double & operator [] (RegFile index)
+ {
+ //Only 32 single floats should be accessed
+ index &= 0x1F
+ return ((float [])parent->rawRegs)[index];
+ }
+ }
+ public:
+ void inline serialize(std::ostream & os)
+ {
+ SERIALIZE_ARRAY(regDump, 32);
+ }
+
+ void inline unserialize(Checkpoint &* cp, std::string & section)
+ {
+ UNSERIALIZE_ARRAY(regDump, 32);
+ }
+
+ QuadRegs quadRegs;
+ DoubleRegs doubleRegs;
+ SingleRegs singleRegs;
+ FloatRegFile() : quadRegs(this), doubleRegs(this), singleRegs(this)
+ {;}
+ };
+
+ // control register file contents
+ typedef uint64_t MiscReg;
+ // The control registers, broken out into fields
+ class MiscRegFile
+ {
+ public:
+ union
+ {
+ uint16_t pstate; // Process State Register
+ struct
+ {
+ uint16_t ag:1; // Alternate Globals
+ uint16_t ie:1; // Interrupt enable
+ uint16_t priv:1; // Privelege mode
+ uint16_t am:1; // Address mask
+ uint16_t pef:1; // PSTATE enable floating-point
+ uint16_t red:1; // RED (reset, error, debug) state
+ uint16_t mm:2; // Memory Model
+ uint16_t tle:1; // Trap little-endian
+ uint16_t cle:1; // Current little-endian
+ } pstateFields;
+ }
+ uint64_t tba; // Trap Base Address
+ union
+ {
+ uint64_t y; // Y (used in obsolete multiplication)
+ struct
+ {
+ uint64_t value:32; // The actual value stored in y
+ const uint64_t :32; // reserved bits
+ } yFields;
+ }
+ uint8_t pil; // Process Interrupt Register
+ uint8_t cwp; // Current Window Pointer
+ uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured on the previous level)
+ union
+ {
+ uint8_t ccr; // Condition Code Register
+ struct
+ {
+ union
+ {
+ uint8_t icc:4; // 32-bit condition codes
+ struct
+ {
+ uint8_t c:1; // Carry
+ uint8_t v:1; // Overflow
+ uint8_t z:1; // Zero
+ uint8_t n:1; // Negative
+ } iccFields:4;
+ } :4;
+ union
+ {
+ uint8_t xcc:4; // 64-bit condition codes
+ struct
+ {
+ uint8_t c:1; // Carry
+ uint8_t v:1; // Overflow
+ uint8_t z:1; // Zero
+ uint8_t n:1; // Negative
+ } xccFields:4;
+ } :4;
+ } ccrFields;
+ }
+ uint8_t asi; // Address Space Identifier
+ uint8_t tl; // Trap Level
+ uint64_t tpc[MaxTL]; // Trap Program Counter (value from previous trap level)
+ uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from previous trap level)
+ union
+ {
+ uint64_t tstate[MaxTL]; // Trap State
+ struct
+ {
+ //Values are from previous trap level
+ uint64_t cwp:5; // Current Window Pointer
+ const uint64_t :2; // Reserved bits
+ uint64_t pstate:10; // Process State
+ const uint64_t :6; // Reserved bits
+ uint64_t asi:8; // Address Space Identifier
+ uint64_t ccr:8; // Condition Code Register
+ } tstateFields[MaxTL];
+ }
+ union
+ {
+ uint64_t tick; // Hardware clock-tick counter
+ struct
+ {
+ uint64_t counter:63; // Clock-tick count
+ uint64_t npt:1; // Non-priveleged trap
+ } tickFields;
+ }
+ uint8_t cansave; // Savable windows
+ uint8_t canrestore; // Restorable windows
+ uint8_t otherwin; // Other windows
+ uint8_t cleanwin; // Clean windows
+ union
+ {
+ uint8_t wstate; // Window State
+ struct
+ {
+ uint8_t normal:3; // Bits TT<4:2> are set to on a normal
+ // register window trap
+ uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin"
+ // register window trap
+ } wstateFields;
+ }
+ union
+ {
+ uint64_t ver; // Version
+ struct
+ {
+ uint64_t maxwin:5; // Max CWP value
+ const uint64_t :2; // Reserved bits
+ uint64_t maxtl:8; // Maximum trap level
+ const uint64_t :8; // Reserved bits
+ uint64_t mask:8; // Processor mask set revision number
+ uint64_t impl:16; // Implementation identification number
+ uint64_t manuf:16; // Manufacturer code
+ } verFields;
+ }
+ union
+ {
+ uint64_t fsr; // Floating-Point State Register
+ struct
+ {
+ union
+ {
+ uint64_t cexc:5; // Current excpetion
+ struct
+ {
+ uint64_t nxc:1; // Inexact
+ uint64_t dzc:1; // Divide by zero
+ uint64_t ufc:1; // Underflow
+ uint64_t ofc:1; // Overflow
+ uint64_t nvc:1; // Invalid operand
+ } cexecFields:5;
+ } :5;
+ union
+ {
+ uint64_t aexc:5; // Accrued exception
+ struct
+ {
+ uint64_t nxc:1; // Inexact
+ uint64_t dzc:1; // Divide by zero
+ uint64_t ufc:1; // Underflow
+ uint64_t ofc:1; // Overflow
+ uint64_t nvc:1; // Invalid operand
+ } aexecFields:5;
+ } :5;
+ uint64_t fcc0:2; // Floating-Point condtion codes
+ const uint64_t :1; // Reserved bits
+ uint64_t qne:1; // Deferred trap queue not empty
+ // with no queue, it should read 0
+ uint64_t ftt:3; // Floating-Point trap type
+ uint64_t ver:3; // Version (of the FPU)
+ const uint64_t :2; // Reserved bits
+ uint64_t ns:1; // Nonstandard floating point
+ union
+ {
+ uint64_t tem:5; // Trap Enable Mask
+ struct
+ {
+ uint64_t nxm:1; // Inexact
+ uint64_t dzm:1; // Divide by zero
+ uint64_t ufm:1; // Underflow
+ uint64_t ofm:1; // Overflow
+ uint64_t nvm:1; // Invalid operand
+ } temFields:5;
+ } :5;
+ const uint64_t :2; // Reserved bits
+ uint64_t rd:2; // Rounding direction
+ uint64_t fcc1:2; // Floating-Point condition codes
+ uint64_t fcc2:2; // Floating-Point condition codes
+ uint64_t fcc3:2; // Floating-Point condition codes
+ const uint64_t :26; // Reserved bits
+ } fsrFields;
+ }
+ union
+ {
+ uint8_t fprs; // Floating-Point Register State
+ struct
+ {
+ dl:1; // Dirty lower
+ du:1; // Dirty upper
+ fef:1; // FPRS enable floating-Point
+ } fprsFields;
+ };
+
+ void serialize(std::ostream & os)
+ {
+ SERIALIZE_SCALAR(pstate);
+ SERIAlIZE_SCALAR(tba);
+ SERIALIZE_SCALAR(y);
+ SERIALIZE_SCALAR(pil);
+ SERIALIZE_SCALAR(cwp);
+ SERIALIZE_ARRAY(tt, MaxTL);
+ SERIALIZE_SCALAR(ccr);
+ SERIALIZE_SCALAR(asi);
+ SERIALIZE_SCALAR(tl);
+ SERIALIZE_SCALAR(tpc);
+ SERIALIZE_SCALAR(tnpc);
+ SERIALIZE_ARRAY(tstate, MaxTL);
+ SERIALIZE_SCALAR(tick);
+ SERIALIZE_SCALAR(cansave);
+ SERIALIZE_SCALAR(canrestore);
+ SERIALIZE_SCALAR(otherwin);
+ SERIALIZE_SCALAR(cleanwin);
+ SERIALIZE_SCALAR(wstate);
+ SERIALIZE_SCALAR(ver);
+ SERIALIZE_SCALAR(fsr);
+ SERIALIZE_SCALAR(fprs);
+ }
+
+ void unserialize(Checkpoint &* cp, std::string & section)
+ {
+ UNSERIALIZE_SCALAR(pstate);
+ UNSERIAlIZE_SCALAR(tba);
+ UNSERIALIZE_SCALAR(y);
+ UNSERIALIZE_SCALAR(pil);
+ UNSERIALIZE_SCALAR(cwp);
+ UNSERIALIZE_ARRAY(tt, MaxTL);
+ UNSERIALIZE_SCALAR(ccr);
+ UNSERIALIZE_SCALAR(asi);
+ UNSERIALIZE_SCALAR(tl);
+ UNSERIALIZE_SCALAR(tpc);
+ UNSERIALIZE_SCALAR(tnpc);
+ UNSERIALIZE_ARRAY(tstate, MaxTL);
+ UNSERIALIZE_SCALAR(tick);
+ UNSERIALIZE_SCALAR(cansave);
+ UNSERIALIZE_SCALAR(canrestore);
+ UNSERIALIZE_SCALAR(otherwin);
+ UNSERIALIZE_SCALAR(cleanwin);
+ UNSERIALIZE_SCALAR(wstate);
+ UNSERIALIZE_SCALAR(ver);
+ UNSERIALIZE_SCALAR(fsr);
+ UNSERIALIZE_SCALAR(fprs);
+ }
+ };
+
+ typedef union
+ {
+ IntReg intreg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ struct RegFile
+ {
+ IntRegFile intRegFile; // (signed) integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegFile; // control register file
+
+ Addr pc; // Program Counter
+ Addr npc; // Next Program Counter
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ static StaticInstPtr<AlphaISA> decodeInst(MachInst);
+
+ // return a no-op instruction... used for instruction fetch faults
+ static const MachInst NoopMachInst;
+
+ // Instruction address compression hooks
+ static inline Addr realPCToFetchPC(const Addr &addr)
+ {
+ return addr;
+ }
+
+ static inline Addr fetchPCToRealPC(const Addr &addr)
+ {
+ return addr;
+ }
+
+ // the size of "fetched" instructions (not necessarily the size
+ // of real instructions for PISA)
+ static inline size_t fetchInstSize()
+ {
+ return sizeof(MachInst);
+ }
+
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param xc The execution context.
+ */
+ template <class XC>
+ static void zeroRegisters(XC *xc);
+};
+
+
+typedef MIPSISA 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 VMPageSize = TheISA::VMPageSize;
+const int LogVMPageSize = TheISA::LogVMPageSize;
+const int ZeroReg = TheISA::ZeroReg;
+const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
+const int MaxAddr = (Addr)-1;
+
+#ifndef FULL_SYSTEM
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint64_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint64_t)v;
+ }
+
+ ~SyscallReturn() {}
+
+ SyscallReturn& operator=(const SyscallReturn& s) {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
+
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
+
+
+ private:
+ uint64_t retval;
+ bool success;
+};
+
+#endif
+
+
+#ifdef FULL_SYSTEM
+
+#include "arch/alpha/ev5.hh"
+#endif
+
+#endif // __ARCH_MIPS_ISA_TRAITS_HH__
diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript
new file mode 100644
index 000000000..d8a3749a1
--- /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.
+arch_base_sources = Split('''
+ arch/sparc/decoder.cc
+ arch/sparc/alpha_o3_exec.cc
+ arch/sparc/fast_cpu_exec.cc
+ arch/sparc/simple_cpu_exec.cc
+ arch/sparc/full_cpu_exec.cc
+ arch/sparc/faults.cc
+ arch/sparc/isa_traits.cc
+ ''')
+
+# Full-system sources
+arch_full_system_sources = Split('''
+ arch/sparc/alpha_memory.cc
+ arch/sparc/arguments.cc
+ arch/sparc/ev5.cc
+ arch/sparc/osfpal.cc
+ arch/sparc/stacktrace.cc
+ arch/sparc/vtophys.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+arch_syscall_emulation_sources = Split('''
+ arch/sparc/alpha_common_syscall_emul.cc
+ arch/sparc/alpha_linux_process.cc
+ arch/sparc/alpha_tru64_process.cc
+ ''')
+
+sources = arch_base_sources
+
+if env['FULL_SYSTEM']:
+ sources += arch_full_system_sources
+ if env['ALPHA_TLASER']:
+ sources += arch_turbolaser_sources
+else:
+ sources += arch_syscall_emulation_sources
+
+for opt in env.ExportOptions:
+ env.ConfigFile(opt)
+
+Return('sources')
diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa
new file mode 100644
index 000000000..b504f1906
--- /dev/null
+++ b/arch/sparc/isa/base.isa
@@ -0,0 +1,82 @@
+////////////////////////////////////////////////////////////////////
+//
+// Base class for sparc instructions, and some support functions
+//
+
+output header {{
+ /**
+ * Base class for all SPARC static instructions.
+ */
+ class SparcStaticInst : public StaticInst<SPARCISA>
+ {
+ protected:
+
+ // Constructor.
+ SparcStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : StaticInst<SPARCISA>(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ bool passesCondition(struct {uint8_t c:1; uint8_t v:1; uint8_t z:1; uint8_t n:1} codes, uint8_t condition);
+}};
+
+output decoder {{
+
+ std::string SparcStaticInst::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();
+ }
+
+ bool passesCondition(struct {uint8_t c:1; uint8_t v:1; uint8_t z:1; uint8_t n:1} codes, uint8_t condition)
+ {
+ switch(condition)
+ {
+ case 0b1000: return true;
+ case 0b0000: return false;
+ case 0b1001: return !codes.z;
+ case 0b0001: return codes.z;
+ case 0b1010: return !(codes.z | (codes.n ^ codes.v));
+ case 0b0010: return codes.z | (codes.n ^ codes.v);
+ case 0b1011: return !(codes.n ^ codes.v);
+ case 0b0011: return (codes.n ^ codes.v);
+ case 0b1100: return !(codes.c | codes.z);
+ case 0b0100: return (codes.c | codes.z);
+ case 0b1101: return !codes.c;
+ case 0b0101: return codes.c;
+ case 0b1110: return !codes.n;
+ case 0b0110: return codes.n;
+ case 0b1111: return !codes.v;
+ case 0b0111: return codes.v;
+ }
+ }
+}};
+
diff --git a/arch/sparc/isa/bitfields.isa b/arch/sparc/isa/bitfields.isa
new file mode 100644
index 000000000..b0ac57575
--- /dev/null
+++ b/arch/sparc/isa/bitfields.isa
@@ -0,0 +1,50 @@
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Bitfields are shared liberally between instruction formats, so they are
+// simply defined alphabetically
+
+def bitfield A <29>;
+def bitfield CC02 <20>;
+def bitfield CC03 <25>;
+def bitfield CC04 <11>;
+def bitfield CC12 <21>;
+def bitfield CC13 <26>;
+def bitfield CC14 <12>;
+def bitfield CC2 <18>;
+def bitfield CMASK <6:4>;
+def bitfield COND2 <28:25>;
+def bitfield COND4 <17:14>;
+def bitfield D16HI <21:20>;
+def bitfield D16LO <13:0>;
+def bitfield DISP19 <18:0>;
+def bitfield DISP22 <21:0>;
+def bitfield DISP30 <29:0>;
+def bitfield FCN <29:26>;
+def bitfield I <13>;
+def bitfield IMM_ASI <12:5>;
+def bitfield IMM22 <21:0>;
+def bitfield MMASK <3:0>;
+def bitfield OP <31:30>;
+def bitfield OP2 <24:22>;
+def bitfield OP3 <24:19>;
+def bitfield OPF <13:5>;
+def bitfield OPF_CC <13:11>;
+def bitfield OPF_LOW5 <9:5>;
+def bitfield OPF_LOW6 <10:5>;
+def bitfield P <19>;
+def bitfield RCOND2 <27:25>;
+def bitfield RCOND3 <12:10>;
+def bitfield RCOND4 <12:10>;
+def bitfield RD <29:25>;
+def bitfield RS1 <18:14>;
+def bitfield RS2 <4:0>;
+def bitfield SHCNT32 <4:0>;
+def bitfield SHCNT64 <5:0>;
+def bitfield SIMM10 <9:0>;
+def bitfield SIMM11 <10:0>;
+def bitfield SIMM13 <12:0>;
+def bitfield SW_TRAP <6:0>;
+def bitfield X <12>;
diff --git a/arch/sparc/isa/decoder.isa b/arch/sparc/isa/decoder.isa
new file mode 100644
index 000000000..06834ecc3
--- /dev/null
+++ b/arch/sparc/isa/decoder.isa
@@ -0,0 +1,638 @@
+////////////////////////////////////////////////////////////////////
+//
+// The actual decoder specification
+//
+
+decode OP default Trap::unknown({{illegal_instruction}}) {
+
+ 0x0: decode OP2 {
+ 0x0: Trap::illtrap({{illegal_instruction}}); //ILLTRAP
+ 0x1: Branch::bpcc({{
+ switch((CC12 << 1) | CC02)
+ {
+ case 1: case 3:
+ throw illegal_instruction;
+ case 0:
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2))
+ ;//branchHere
+ break;
+ case 2:
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, COND2))
+ ;//branchHere
+ break;
+ }
+ }});//BPcc
+ 0x2: Branch::bicc({{
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2))
+ ;//branchHere
+ }});//Bicc
+ 0x3: Branch::bpr({{
+ switch(RCOND)
+ {
+ case 0: case 4:
+ throw illegal_instruction;
+ case 1:
+ if(Rs1 == 0) ;//branchHere
+ break;
+ case 2:
+ if(Rs1 <= 0) ;//branchHere
+ break;
+ case 3:
+ if(Rs1 < 0) ;//branchHere
+ break;
+ case 5:
+ if(Rs1 != 0) ;//branchHere
+ break;
+ case 6:
+ if(Rs1 > 0) ;//branchHere
+ break;
+ case 7:
+ if(Rs1 >= 0) ;//branchHere
+ break;
+ }
+ }}); //BPr
+ 0x4: IntegerOp::sethi({{Rd = (IMM22 << 10) & 0xFFFFFC00;}}); //SETHI (or NOP if rd == 0 and imm == 0)
+ 0x5: Trap::fbpfcc({{throw fp_disabled;}}); //FBPfcc
+ 0x6: Trap::fbfcc({{throw fp_disabled;}}); //FBfcc
+ }
+ 0x1: Branch::call({{
+ //branch here
+ Rd = xc->pc;
+ }});
+ 0x2: decode OP3 {
+ format IntegerOp {
+ 0x00: add({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ Rd = Rs1.sdw + val2;
+ }});//ADD
+ 0x01: and({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw & val2;
+ }});//AND
+ 0x02: or({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw | val2;
+ }});//OR
+ 0x03: xor({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw ^ val2;
+ }});//XOR
+ 0x04: sub({{
+ INT64 val2 = ~((UINT64)(I ? SIMM13.sdw : Rs2.udw))+1;
+ Rd = Rs1.sdw + val2;
+ }});//SUB
+ 0x05: andn({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw & ~val2;
+ }});//ANDN
+ 0x06: orn({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw | ~val2;
+ }});//ORN
+ 0x07: xnor({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = ~(Rs1.udw ^ val2);
+ }});//XNOR
+ 0x08: addc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ INT64 carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
+ Rd = Rs1.sdw + val2 + carryin;
+ }});//ADDC
+ 0x09: mulx({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 * val2;
+ }});//MULX
+ 0x0A: umul({{
+ UINT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = resTemp = Rs1.udw<31:0> * val2<31:0>;
+ xc->regs.MiscRegs.yFields.value = resTemp<63:32>;
+ }});//UMUL
+ 0x0B: smul({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ rd.sdw = resTemp = Rs1.sdw<31:0> * val2<31:0>;
+ xc->regs.MiscRegs.yFields.value = resTemp<63:32>;
+ }});//SMUL
+ 0x0C: subc({{
+ INT64 val2 = ~((INT64)(I ? SIMM13.sdw : Rs2.sdw))+1;
+ INT64 carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
+ Rd.sdw = Rs1.sdw + val2 + carryin;
+ }});//SUBC
+ 0x0D: udivx({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ if(val2 == 0) throw division_by_zero;
+ Rd.udw = Rs1.udw / val2;
+ }});//UDIVX
+ 0x0E: udiv({{
+ UINT32 resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>);
+ if(val2 == 0) throw division_by_zero;
+ resTemp = (UINT64)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.udw<31:0>) / val2;
+ INT32 overflow = (resTemp<63:32> != 0);
+ if(overflow) rd.udw = resTemp = 0xFFFFFFFF;
+ else rd.udw = resTemp;
+ }}); //UDIV
+ 0x0F: sdiv({{
+ INT32 resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>);
+ if(val2 == 0) throw division_by_zero;
+ Rd.sdw = resTemp = (INT64)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.sdw<31:0>) / val2;
+ INT32 overflow = (resTemp<63:31> != 0);
+ INT32 underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF);
+ if(overflow) rd.udw = resTemp = 0x7FFFFFFF;
+ else if(underflow) rd.udw = resTemp = 0xFFFFFFFF80000000;
+ else rd.udw = resTemp;
+ }});//SDIV
+ }
+ format IntegerOpCc {
+ 0x10: addcc({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );//ADDcc
+ 0x11: andcc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 & val2;}}
+ ,{{0}},{{0}},{{0}},{{0}});//ANDcc
+ 0x12: orcc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 | val2;}}
+ ,{{0}},{{0}},{{0}},{{0}});//ORcc
+ 0x13: xorcc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 ^ val2;}}
+ ,{{0}},{{0}},{{0}},{{0}});//XORcc
+ 0x14: subcc({{
+ INT64 resTemp, val2 = (INT64)(I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 - val2;}},
+ {{((Rs1 & 0xFFFFFFFF + (~val2) & 0xFFFFFFFF + 1) >> 31)}},
+ {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
+ {{((Rs1 >> 1) + (~val2) >> 1) + ((Rs1 | ~val2) & 0x1))<63:>}},
+ {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
+ );//SUBcc
+ 0x15: andncc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 & ~val2;}}
+ ,{{0}},{{0}},{{0}},{{0}});//ANDNcc
+ 0x16: orncc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 | ~val2;}}
+ ,{{0}},{{0}},{{0}},{{0}});//ORNcc
+ 0x17: xnorcc({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = ~(Rs1 ^ val2);}}
+ ,{{0}},{{0}},{{0}},{{0}});//XNORcc
+ 0x18: addccc({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ INT64 carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
+ Rd = resTemp = Rs1 + val2 + carryin;}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31 + carryin)}},
+ {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
+ {{((Rs1 >> 1) + (val2 >> 1) + ((Rs1 & val2) | (carryin & (Rs1 | val2)) & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );//ADDCcc
+ 0x1A: umulcc({{
+ UINT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1.udw<31:0> * val2<31:0>;
+ xc->regs.MiscRegs.yFields.value = resTemp<63:32>;}}
+ ,{{0}},{{0}},{{0}},{{0}});//UMULcc
+ 0x1B: smulcc({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1.sdw<31:0> * val2<31:0>;
+ xc->regs.MiscRegs.yFields.value = resTemp<63:32>;}}
+ ,{{0}},{{0}},{{0}},{{0}});//SMULcc
+ 0x1C: subccc({{
+ INT64 resTemp, val2 = (INT64)(I ? SIMM13.sdw : Rs2);
+ INT64 carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
+ Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}},
+ {{((Rs1 & 0xFFFFFFFF + (~(val2 + carryin)) & 0xFFFFFFFF + 1) >> 31)}},
+ {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
+ {{((Rs1 >> 1) + (~(val2 + carryin)) >> 1) + ((Rs1 | ~(val2+carryin)) & 0x1))<63:>}},
+ {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
+ );//SUBCcc
+ 0x1D: udivxcc({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.udw);
+ if(val2 == 0) throw division_by_zero;
+ Rd.udw = Rs1.udw / val2;}}
+ ,{{0}},{{0}},{{0}},{{0}});//UDIVXcc
+ 0x1E: udivcc({{
+ UINT32 resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>);
+ if(val2 == 0) throw division_by_zero;
+ resTemp = (UINT64)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.udw<31:0>) / val2;
+ INT32 overflow = (resTemp<63:32> != 0);
+ if(overflow) rd.udw = resTemp = 0xFFFFFFFF;
+ else rd.udw = resTemp;}},
+ {{0}},
+ {{overflow}},
+ {{0}},
+ {{0}}
+ );//UDIVcc
+ 0x1F: sdivcc({{
+ INT32 resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>);
+ if(val2 == 0) throw division_by_zero;
+ Rd.sdw = resTemp = (INT64)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.sdw<31:0>) / val2;
+ INT32 overflow = (resTemp<63:31> != 0);
+ INT32 underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF);
+ if(overflow) rd.udw = resTemp = 0x7FFFFFFF;
+ else if(underflow) rd.udw = resTemp = 0xFFFFFFFF80000000;
+ else rd.udw = resTemp;}},
+ {{0}},
+ {{overflow || underflow}},
+ {{0}},
+ {{0}}
+ );//SDIVcc
+ 0x20: taddcc({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ INT32 overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{overflow}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );//TADDcc
+ 0x21: tsubcc({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ INT32 overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
+ {{(Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{overflow}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );//TSUBcc
+ 0x22: taddcctv({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ INT32 overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
+ if(overflow) throw tag_overflow;}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{overflow}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );//TADDccTV
+ 0x23: tsubcctv({{
+ INT64 resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ INT32 overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
+ if(overflow) throw tag_overflow;}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{overflow}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );//TSUBccTV
+ 0x24: mulscc({{
+ INT64 resTemp, multiplicand = (I ? SIMM13.sdw : Rs2);
+ INT32 multiplier = Rs1<31:0>;
+ INT32 savedLSB = Rs1<0:>;
+ multiplier = multipler<31:1> |
+ ((xc->regs.MiscRegs.ccrFields.iccFields.n
+ ^ xc->regs.MiscRegs.ccrFields.iccFields.v) << 32);
+ if(!xc->regs.MiscRegs.yFields.value<0:>)
+ multiplicand = 0;
+ Rd = resTemp = multiplicand + multiplier;
+ xc->regs.MiscRegs.yFields.value = xc->regs.MiscRegs.yFields.value<31:1> | (savedLSB << 31);}},
+ {{((multiplicand & 0xFFFFFFFF + multiplier & 0xFFFFFFFF) >> 31)}},
+ {{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}},
+ {{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}},
+ {{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}}
+ );//MULScc
+ }
+ format IntegerOp
+ {
+ 0x25: decode X {
+ 0x0: sll({{Rd = Rs1 << (I ? SHCNT32 : Rs2<4:0>);}}); //SLL
+ 0x1: sllx({{Rd = Rs1 << (I ? SHCNT64 : Rs2<5:0>);}}); //SLLX
+ }
+ 0x26: decode X {
+ 0x0: srl({{Rd = Rs1.udw<31:0> >> (I ? SHCNT32 : Rs2<4:0>);}}); //SRL
+ 0x1: srlx({{Rd = Rs1.udw >> (I ? SHCNT64 : Rs2<5:0>);}});//SRLX
+ }
+ 0x27: decode X {
+ 0x0: sra({{Rd = Rs1.sdw<31:0> >> (I ? SHCNT32 : Rs2<4:0>);}}); //SRA
+ 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});//SRAX
+ }
+ 0x28: decode RS1 {
+ 0x0: rdy({{Rd = xc->regs.MiscRegs.yFields.value;}}); //RDY
+ 0x2: rdccr({{Rd = xc->regs.MiscRegs.ccr;}}); //RDCCR
+ 0x3: rdasi({{Rd = xc->regs.MiscRegs.asi;}}); //RDASI
+ 0x4: rdtick({{
+ if(xc->regs.MiscRegs.pstateFields.priv == 0 &&
+ xc->regs.MiscRegs.tickFields.npt == 1)
+ throw privileged_action;
+ Rd = xc->regs.MiscRegs.tick;
+ }});//RDTICK
+ 0x5: rdpc({{Rd = xc->regs.pc;}}); //RDPC
+ 0x6: rdfprs({{Rd = xc->regs.MiscRegs.fprs;}}); //RDFPRS
+ 0xF: decode I {
+ 0x0: Noop::membar({{//Membar isn't needed yet}}); //MEMBAR
+ 0x1: Noop::stbar({{//Stbar isn/'t needed yet}}); //STBAR
+ }
+ }
+
+ 0x2A: decode RS1 {
+ 0x0: rdprtpc({{checkPriv Rd = xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl];}});
+ 0x1: rdprtnpc({{checkPriv Rd = xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl];}});
+ 0x2: rdprtstate({{checkPriv Rd = xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl];}});
+ 0x3: rdprtt({{checkPriv Rd = xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl];}});
+ 0x4: rdprtick({{checkPriv Rd = xc->regs.MiscRegs.tick;}});
+ 0x5: rdprtba({{checkPriv Rd = xc->regs.MiscRegs.tba;}});
+ 0x6: rdprpstate({{checkPriv Rd = xc->regs.MiscRegs.pstate;}});
+ 0x7: rdprtl({{checkPriv Rd = xc->regs.MiscRegs.tl;}});
+ 0x8: rdprpil({{checkPriv Rd = xc->regs.MiscRegs.pil;}});
+ 0x9: rdprcwp({{checkPriv Rd = xc->regs.MiscRegs.cwp;}});
+ 0xA: rdprcansave({{checkPriv Rd = xc->regs.MiscRegs.cansave;}});
+ 0xB: rdprcanrestore({{checkPriv Rd = xc->regs.MiscRegs.canrestore;}});
+ 0xC: rdprcleanwin({{checkPriv Rd = xc->regs.MiscRegs.cleanwin;}});
+ 0xD: rdprotherwin({{checkPriv Rd = xc->regs.MiscRegs.otherwin;}});
+ 0xE: rdprwstate({{checkPriv Rd = xc->regs.MiscRegs.wstate;}});
+ 0xF: rdprfq({{throw illegal_instruction;}}); //The floating point queue isn't implemented right now.
+ }
+ 0x2B: BasicOperate::flushw({{\\window toilet}}); //FLUSHW
+ 0x2C: movcc({{
+ ccBank = (CC24 << 2) | (CC14 << 1) | (CC04 << 0);
+ switch(ccBank)
+ {
+ case 0: case 1: case 2: case 3:
+ throw fp_disabled;
+ break;
+ case 5: case 7:
+ throw illegal_instruction;
+ break;
+ case 4:
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND4))
+ Rd = (I ? SIMM11.sdw : RS2);
+ break;
+ case 6:
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, COND4))
+ Rd = (I ? SIMM11.sdw : RS2);
+ break;
+ }
+ }});//MOVcc
+ 0x2D: sdivx({{
+ INT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ if(val2 == 0) throw division_by_zero;
+ Rd.sdw = Rs1.sdw / val2;
+ }});//SDIVX
+ 0x2E: decode RS1 {
+ 0x0: IntegerOp::popc({{
+ INT64 count = 0, val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ UINT8 oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}
+ for(unsigned int x = 0; x < 16; x++)
+ {
+ count += oneBits[val2 & 0xF];
+ val2 >> 4;
+ }
+ }});//POPC
+ }
+ 0x2F: movr({{
+ UINT64 val2 = (I ? SIMM10.sdw : Rs2.sdw);
+ switch(RCOND)
+ {
+ case 0: case 4:
+ throw illegal_instruction;
+ break;
+ case 1:
+ if(Rs1 == 0) Rd = val2;
+ break;
+ case 2:
+ if(Rs1 <= 0) Rd = val2;
+ break;
+ case 3:
+ if(Rs1 = 0) Rd = val2;
+ break;
+ case 5:
+ if(Rs1 != 0) Rd = val2;
+ break;
+ case 6:
+ if(Rs1 > 0) Rd = val2;
+ break;
+ case 7:
+ if(Rs1 >= 0) Rd = val2;
+ break;
+ }
+ }});//MOVR
+ 0x30: decode RD {
+ 0x0: wry({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.y = Rs1 ^ val2;
+ }});//WRY
+ 0x2: wrccr({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.ccr = Rs1 ^ val2;
+ }});//WRCCR
+ 0x3: wrasi({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.asi = Rs1 ^ val2;
+ }});//WRASI
+ 0x6: wrfprs({{
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.asi = Rs1 ^ val2;
+ }});//WRFPRS
+ 0xF: Trap::sir({{software_initiated_reset}}); //SIR
+ }
+ 0x31: decode FCN {
+ 0x0: BasicOperate::saved({{\\Boogy Boogy}}); //SAVED
+ 0x1: BasicOperate::restored({{\\Boogy Boogy}}); //RESTORED
+ }
+ 0x32: decode RD {
+ 0x0: wrprtpc({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x1: wrprtnpc({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x2: wrprtstate({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x3: wrprtt({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x4: wrprtick({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tick = Rs1 ^ val2;
+ }});
+ 0x5: wrprtba({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tba = Rs1 ^ val2;
+ }});
+ 0x6: wrprpstate({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.pstate = Rs1 ^ val2;
+ }});
+ 0x7: wrprtl({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tl = Rs1 ^ val2;
+ }});
+ 0x8: wrprpil({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.pil = Rs1 ^ val2;
+ }});
+ 0x9: wrprcwp({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.cwp = Rs1 ^ val2;
+ }});
+ 0xA: wrprcansave({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.cansave = Rs1 ^ val2;
+ }});
+ 0xB: wrprcanrestore({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.canrestore = Rs1 ^ val2;
+ }});
+ 0xC: wrprcleanwin({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.cleanwin = Rs1 ^ val2;
+ }});
+ 0xD: wrprotherwin({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.otherwin = Rs1 ^ val2;
+ }});
+ 0xE: wrprwstate({{checkPriv
+ UINT64 val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.wstate = Rs1 ^ val2;
+ }});
+ }
+
+ 0x34: Trap::fpop1({{Throw fp_disabled;}}); //FPOP1
+ 0x35: Trap::fpop2({{Throw fp_disabled;}}); //FPOP2
+
+
+ 0x38: Branch::jmpl({{//Stuff}}); //JMPL
+ 0x39: Branch::return({{//Other Stuff}}); //RETURN
+ 0x3A: Trap::tcc({{
+ switch((CC14 << 1) | (CC04 << 0))
+ {
+ case 1: case 3:
+ throw illegal_instruction;
+ case 0:
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, machInst<25:28>))
+ throw trap_instruction;
+ break;
+ case 2:
+ if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, machInst<25:28>))
+ throw trap_instruction;
+ break;
+ }
+ }}); //Tcc
+ 0x3B: BasicOperate::flush({{//Lala}}); //FLUSH
+ 0x3C: BasicOperate::save({{//leprechauns); //SAVE
+ 0x3D: BasicOperate::restore({{//Eat my short int}}); //RESTORE
+ 0x3E: decode FCN {
+ 0x1: BasicOperate::done({{//Done thing}}); //DONE
+ 0x2: BasicOperate::retry({{//Retry thing}}); //RETRY
+ }
+ }
+ }
+ 0x3: decode OP3 {
+ format Mem {
+ 0x00: lduw({{Rd.uw = Mem.uw;}}); //LDUW
+ 0x01: ldub({{Rd.ub = Mem.ub;}}); //LDUB
+ 0x02: lduh({{Rd.uhw = Mem.uhw;}}); //LDUH
+ 0x03: ldd({{
+ UINT64 val = Mem.udw;
+ setIntReg(RD & (~1), val<31:0>);
+ setIntReg(RD | 1, val<63:32>);
+ }});//LDD
+ 0x04: stw({{Mem.sw = Rd.sw;}}); //STW
+ 0x05: stb({{Mem.sb = Rd.sb;}}); //STB
+ 0x06: sth({{Mem.shw = Rd.shw;}}); //STH
+ 0x07: std({{
+ Mem.udw = readIntReg(RD & (~1))<31:0> | (readIntReg(RD | 1)<31:0> << 32);
+ }});//STD
+ 0x08: ldsw({{Rd.sw = Mem.sw;}}); //LDSW
+ 0x09: ldsb({{Rd.sb = Mem.sb;}}); //LDSB
+ 0x0A: ldsh({{Rd.shw = Mem.shw;}}); //LDSH
+ 0x0B: ldx({{Rd.udw = Mem.udw;}}); //LDX
+
+ 0x0D: ldstub({{
+ Rd.ub = Mem.ub;
+ Mem.ub = 0xFF;
+ }}); //LDSTUB
+ 0x0E: stx({{Rd.udw = Mem.udw;}}); //STX
+ 0x0F: swap({{
+ UINT32 temp = Rd.uw;
+ Rd.uw = Mem.uw;
+ Mem.uw = temp;
+ }}); //SWAP
+ 0x10: lduwa({{Rd.uw = Mem.uw;}}); //LDUWA
+ 0x11: lduba({{Rd.ub = Mem.ub;}}); //LDUBA
+ 0x12: lduha({{Rd.uhw = Mem.uhw;}}); //LDUHA
+ 0x13: ldda({{
+ UINT64 val = Mem.udw;
+ setIntReg(RD & (~1), val<31:0>);
+ setIntReg(RD | 1, val<63:32>);
+ }}); //LDDA
+ 0x14: stwa({{Mem.uw = Rd.uw;}}); //STWA
+ 0x15: stba({{Mem.ub = Rd.ub;}}); //STBA
+ 0x16: stha({{Mem.uhw = Rd.uhw;}}); //STHA
+ 0x17: stda({{
+ Mem.udw = readIntReg(RD & (~1))<31:0> | (readIntReg(RD | 1)<31:0> << 32);
+ }}); //STDA
+ 0x18: ldswa({{Rd.sw = Mem.sw;}}); //LDSWA
+ 0x19: ldsba({{Rd.sb = Mem.sb;}}); //LDSBA
+ 0x1A: ldsha({{Rd.shw = Mem.shw;}}); //LDSHA
+ 0x1B: ldxa({{Rd.sdw = Mem.sdw;}}); //LDXA
+
+ 0x1D: ldstuba({{
+ Rd.ub = Mem.ub;
+ Mem.ub = 0xFF;
+ }}); //LDSTUBA
+ 0x1E: stxa({{Mem.sdw = Rd.sdw}}); //STXA
+ 0x1F: swapa({{
+ UINT32 temp = Rd.uw;
+ Rd.uw = Mem.uw;
+ Mem.uw = temp;
+ }}); //SWAPA
+ 0x20: Trap::ldf({{throw fp_disabled;}}); //LDF
+ 0x21: decode X {
+ 0x0: Trap::ldfsr({{throw fp_disabled;}}); //LDFSR
+ 0x1: Trap::ldxfsr({{throw fp_disabled;}}); //LDXFSR
+ }
+ 0x22: Trap::ldqf({{throw fp_disabled;}}); //LDQF
+ 0x23: Trap::lddf({{throw fp_disabled;}}); //LDDF
+ 0x24: Trap::stf({{throw fp_disabled;}}); //STF
+ 0x25: decode X {
+ 0x0: Trap::stfsr({{throw fp_disabled;}}); //STFSR
+ 0x1: Trap::stxfsr({{throw fp_disabled;}}); //STXFSR
+ }
+ 0x26: Trap::stqf({{throw fp_disabled;}}); //STQF
+ 0x27: Trap::stdf({{throw fp_disabled;}}); //STDF
+
+
+
+
+
+ 0x2D: Noop::prefetch({{ }}); //PREFETCH
+
+
+ 0x30: Trap::ldfa({{throw fp_disabled;}}); //LDFA
+
+ 0x32: Trap::ldqfa({{throw fp_disabled;}}); //LDQFA
+ 0x33: Trap::lddfa({{throw fp_disabled;}}); //LDDFA
+ 0x34: Trap::stfa({{throw fp_disabled;}}); //STFA
+ 0x35: Trap::stqfa({{throw fp_disabled;}}); //STQFA
+ 0x36: Trap::stdfa({{throw fp_disabled;}}); //STDFA
+
+
+
+
+
+ 0x3C: Cas::casa(
+ {{UINT64 val = Mem.uw;
+ if(Rs2.uw == val)
+ Mem.uw = Rd.uw;
+ Rd.uw = val;
+ }}); //CASA
+ 0x3D: Noop::prefetcha({{ }}); //PREFETCHA
+ 0x3E: Cas::casxa(
+ {{UINT64 val = Mem.udw;
+ if(Rs2 == val)
+ Mem.udw = Rd;
+ Rd = val;
+ }}); //CASXA
+ }
+ }
+}
diff --git a/arch/sparc/isa/formats.isa b/arch/sparc/isa/formats.isa
new file mode 100644
index 000000000..547f8be48
--- /dev/null
+++ b/arch/sparc/isa/formats.isa
@@ -0,0 +1,19 @@
+//Include the basic format
+//Templates from this format are used later
+##include "m5/arch/sparc/isa/formats/basic.isa"
+
+//Include the integerOp and integerOpCc format
+##include "m5/arch/sparc/isa/formats/integerop.isa"
+
+//Include the mem format
+##include "m5/arch/sparc/isa/formats/mem.isa"
+
+//Include the trap format
+##include "m5/arch/sparc/isa/formats/trap.isa"
+
+//Include the branch format
+##include "m5/arch/sparc/isa/formats/branch.isa"
+
+//Include the noop format
+##include "m5/arch/sparc/isa/formats/noop.isa"
+
diff --git a/arch/sparc/isa/formats/basic.isa b/arch/sparc/isa/formats/basic.isa
new file mode 100644
index 000000000..1994df41c
--- /dev/null
+++ b/arch/sparc/isa/formats/basic.isa
@@ -0,0 +1,65 @@
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ /// Constructor.
+ %(class_name)s(MachInst machInst);
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if(fault == No_Fault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// The most basic instruction format... used only for a few misc. insts
+def format BasicOperate(code, *flags) {{
+ iop = InstObjParams(name, Name, 'SparcStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
diff --git a/arch/sparc/isa/formats/branch.isa b/arch/sparc/isa/formats/branch.isa
new file mode 100644
index 000000000..c4c0a90af
--- /dev/null
+++ b/arch/sparc/isa/formats/branch.isa
@@ -0,0 +1,66 @@
+////////////////////////////////////////////////////////////////////
+//
+// Branch instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Branch : public SparcStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+def template BranchExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ //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(SparcException 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 Branch(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+ exec_output = BranchExecute.subst(iop)
+}};
diff --git a/arch/sparc/isa/formats/integerop.isa b/arch/sparc/isa/formats/integerop.isa
new file mode 100644
index 000000000..275a346d3
--- /dev/null
+++ b/arch/sparc/isa/formats/integerop.isa
@@ -0,0 +1,110 @@
+////////////////////////////////////////////////////////////////////
+//
+// Integer operate instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class IntegerOp : public SparcStaticInst
+ {
+ protected:
+
+ /// Constructor
+ IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string IntegerOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+def template IntegerExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ //These are set to constants when the execute method
+ //is generated
+ bool useCc = ;
+ bool checkPriv = ;
+
+ //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(SparcException except)
+ {
+ //Deal with exception
+ return No_Fault;
+ }
+
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ if(useCc)
+ {
+ xc->regs.miscRegFile.ccrFields.iccFields.n = Rd & (1 << 63);
+ xc->regs.miscRegFile.ccrFields.iccFields.z = (Rd == 0);
+ xc->regs.miscRegFile.ccrFields.iccFields.v = ivValue;
+ xc->regs.miscRegFile.ccrFields.iccFields.c = icValue;
+ xc->regs.miscRegFile.ccrFields.xccFields.n = Rd & (1 << 31);
+ xc->regs.miscRegFile.ccrFields.xccFields.z = ((Rd & 0xFFFFFFFF) == 0);
+ xc->regs.miscRegFile.ccrFields.xccFields.v = xvValue;
+ xc->regs.miscRegFile.ccrFields.xccFields.c = xcValue;
+ }
+ return No_Fault;
+ }
+}};
+
+// Primary format for integer operate instructions:
+def format IntegerOp(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, 'SparcStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+ exec_output = IntegerExecute.subst(iop)
+}};
+
+// Primary format for integer operate instructions:
+def format IntegerOpCc(code, icValue, ivValue, xcValue, xvValue, *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', ivValue), ('icValue', icValue),
+ ('xvValue', xvValue), ('xcValue', xcValue)):
+ code.replace(marker, value)
+ iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+ exec_output = IntegerExecute.subst(iop)
+}};
diff --git a/arch/sparc/isa/formats/mem.isa b/arch/sparc/isa/formats/mem.isa
new file mode 100644
index 000000000..abc00b6f2
--- /dev/null
+++ b/arch/sparc/isa/formats/mem.isa
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////
+//
+// Mem instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Mem : public SparcStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Mem(const char *mnem, MachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+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(SparcException 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, 'SparcStaticInst', 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, 'SparcStaticInst', 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;');
+}};
diff --git a/arch/sparc/isa/formats/noop.isa b/arch/sparc/isa/formats/noop.isa
new file mode 100644
index 000000000..bc83e3261
--- /dev/null
+++ b/arch/sparc/isa/formats/noop.isa
@@ -0,0 +1,47 @@
+////////////////////////////////////////////////////////////////////
+//
+// Noop instruction
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Noop : public SparcStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Noop(const char *mnem, MachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Noop::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+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;
+ }
+}};
+
+// Primary format for integer operate instructions:
+def format Noop(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+ exec_output = NoopExecute.subst(iop)
+}};
diff --git a/arch/sparc/isa/formats/trap.isa b/arch/sparc/isa/formats/trap.isa
new file mode 100644
index 000000000..bee77fe69
--- /dev/null
+++ b/arch/sparc/isa/formats/trap.isa
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////
+//
+// Trap instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class Trap : public SparcStaticInst
+ {
+ protected:
+
+ /// Constructor
+ Trap(const char *mnem, MachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Trap::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+def template TrapExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ //Call into the trap handler with the appropriate fault
+ 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 Trap(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+ exec_output = TrapExecute.subst(iop)
+}};
diff --git a/arch/sparc/isa/includes.isa b/arch/sparc/isa/includes.isa
new file mode 100644
index 000000000..ff7cb7d1d
--- /dev/null
+++ b/arch/sparc/isa/includes.isa
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "cpu/static_inst.hh"
+#include "traps.hh"
+#include "mem/mem_req.hh" // some constructors use MemReq flags
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+}};
+
+output exec {{
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+#ifdef FULL_SYSTEM
+//#include "arch/alpha/pseudo_inst.hh"
+#endif
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+}};
+
diff --git a/arch/sparc/isa/main.isa b/arch/sparc/isa/main.isa
new file mode 100644
index 000000000..ab0290d58
--- /dev/null
+++ b/arch/sparc/isa/main.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.
+
+##include "m5/arch/sparc/isa/includes.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// SparcISAInst namespace.
+//
+
+namespace SparcISA;
+
+//Include the bitfield definitions
+##include "m5/arch/sparc/isa/bitfields.isa"
+
+//Include the operand_types and operand definitions
+##include "m5/arch/sparc/isa/operands.isa"
+
+//Include the base class for sparc instructions, and some support code
+##include "m5/arch/sparc/isa/base.isa"
+
+//Include the definitions for the instruction formats
+##include "m5/arch/sparc/isa/formats.isa"
+
+//Include the decoder definition
+##include "m5/arch/sparc/isa/decoder.isa"
diff --git a/arch/sparc/isa/operands.isa b/arch/sparc/isa/operands.isa
new file mode 100644
index 000000000..c5ba263d6
--- /dev/null
+++ b/arch/sparc/isa/operands.isa
@@ -0,0 +1,32 @@
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'shw' : ('signed int', 16),
+ 'uhw' : ('unsigned int', 16),
+ 'sw' : ('signed int', 32),
+ 'uw' : ('unsigned int', 32),
+ 'sdw' : ('signed int', 64),
+ 'udw' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64),
+ 'qf' : ('float', 128)
+}};
+
+def operands {{
+ # Int regs default to unsigned, but code should not count on this.
+ # For clarity, descriptions that depend on unsigned behavior should
+ # explicitly specify '.uq'.
+ 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
+ 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 2),
+ 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 3),
+ #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
+ #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
+ #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
+ 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4)
+ #'NPC': ('NPC', 'uq', 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/sparc/isa_traits.hh b/arch/sparc/isa_traits.hh
new file mode 100644
index 000000000..7dd49aed9
--- /dev/null
+++ b/arch/sparc/isa_traits.hh
@@ -0,0 +1,532 @@
+/*
+ * 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_SPARC_ISA_TRAITS_HH__
+#define __ARCH_SPARC_ISA_TRAITS_HH__
+
+//This makes sure the big endian versions of certain functions are used.
+namespace BigEndianGuest {}
+using namespace BigEndianGuest;
+
+#include "arch/sparc/faults.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+class FastCPU;
+//class FullCPU;
+//class Checkpoint;
+
+#define TARGET_SPARC
+
+template <class ISA> class StaticInst;
+template <class ISA> class StaticInstPtr;
+
+//namespace EV5
+//{
+// int DTB_ASN_ASN(uint64_t reg);
+// int ITB_ASN_ASN(uint64_t reg);
+//}
+
+class SPARCISA
+{
+ public:
+
+ typedef uint32_t MachInst;
+ typedef uint64_t Addr;
+ typedef uint8_t RegIndex;
+
+ enum
+ {
+ MemoryEnd = 0xffffffffffffffffULL,
+
+ NumFloatRegs = 32,
+ NumMiscRegs = 32,
+
+ MaxRegsOfAnyType = 32,
+ // Static instruction parameters
+ MaxInstSrcRegs = 3,
+ MaxInstDestRegs = 2,
+
+ // Maximum trap level
+ MaxTL = 4
+
+ // semantically meaningful register indices
+ ZeroReg = 0, // architecturally meaningful
+ // the rest of these depend on the ABI
+ }
+ typedef uint64_t IntReg;
+
+ class IntRegFile
+ {
+ private:
+ //For right now, let's pretend the register file is static
+ IntReg regs[32];
+ public:
+ IntReg & operator [] (RegIndex index)
+ {
+ //Don't allow indexes outside of the 32 registers
+ index &= 0x1F
+ return regs[index];
+ }
+ };
+
+ void inline serialize(std::ostream & os)
+ {
+ SERIALIZE_ARRAY(regs, 32);
+ }
+
+ void inline unserialize(Checkpoint &*cp, const std::string &section)
+ {
+ UNSERIALIZE_ARRAY(regs, 32);
+ }
+
+ class FloatRegFile
+ {
+ private:
+ //By using the largest data type, we ensure everything
+ //is aligned correctly in memory
+ union
+ {
+ double double rawRegs[16];
+ uint64_t regDump[32];
+ };
+ class QuadRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ QuadRegs(FloatRegFile * p) : parent(p) {;}
+ double double & operator [] (RegIndex index)
+ {
+ //Quad floats are index by the single
+ //precision register the start on,
+ //and only 16 should be accessed
+ index = (index >> 2) & 0xF;
+ return parent->rawRegs[index];
+ }
+ };
+ class DoubleRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ DoubleRegs(FloatRegFile * p) : parent(p) {;}
+ double & operator [] (RegIndex index)
+ {
+ //Double floats are index by the single
+ //precision register the start on,
+ //and only 32 should be accessed
+ index = (index >> 1) & 0x1F
+ return ((double [])parent->rawRegs)[index];
+ }
+ }
+ class SingleRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ SingleRegs(FloatRegFile * p) : parent(p) {;}
+ double & operator [] (RegFile index)
+ {
+ //Only 32 single floats should be accessed
+ index &= 0x1F
+ return ((float [])parent->rawRegs)[index];
+ }
+ }
+ public:
+ void inline serialize(std::ostream & os)
+ {
+ SERIALIZE_ARRAY(regDump, 32);
+ }
+
+ void inline unserialize(Checkpoint &* cp, std::string & section)
+ {
+ UNSERIALIZE_ARRAY(regDump, 32);
+ }
+
+ QuadRegs quadRegs;
+ DoubleRegs doubleRegs;
+ SingleRegs singleRegs;
+ FloatRegFile() : quadRegs(this), doubleRegs(this), singleRegs(this)
+ {;}
+ };
+
+ // control register file contents
+ typedef uint64_t MiscReg;
+ // The control registers, broken out into fields
+ class MiscRegFile
+ {
+ public:
+ union
+ {
+ uint16_t pstate; // Process State Register
+ struct
+ {
+ uint16_t ag:1; // Alternate Globals
+ uint16_t ie:1; // Interrupt enable
+ uint16_t priv:1; // Privelege mode
+ uint16_t am:1; // Address mask
+ uint16_t pef:1; // PSTATE enable floating-point
+ uint16_t red:1; // RED (reset, error, debug) state
+ uint16_t mm:2; // Memory Model
+ uint16_t tle:1; // Trap little-endian
+ uint16_t cle:1; // Current little-endian
+ } pstateFields;
+ }
+ uint64_t tba; // Trap Base Address
+ union
+ {
+ uint64_t y; // Y (used in obsolete multiplication)
+ struct
+ {
+ uint64_t value:32; // The actual value stored in y
+ const uint64_t :32; // reserved bits
+ } yFields;
+ }
+ uint8_t pil; // Process Interrupt Register
+ uint8_t cwp; // Current Window Pointer
+ uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured on the previous level)
+ union
+ {
+ uint8_t ccr; // Condition Code Register
+ struct
+ {
+ union
+ {
+ uint8_t icc:4; // 32-bit condition codes
+ struct
+ {
+ uint8_t c:1; // Carry
+ uint8_t v:1; // Overflow
+ uint8_t z:1; // Zero
+ uint8_t n:1; // Negative
+ } iccFields:4;
+ } :4;
+ union
+ {
+ uint8_t xcc:4; // 64-bit condition codes
+ struct
+ {
+ uint8_t c:1; // Carry
+ uint8_t v:1; // Overflow
+ uint8_t z:1; // Zero
+ uint8_t n:1; // Negative
+ } xccFields:4;
+ } :4;
+ } ccrFields;
+ }
+ uint8_t asi; // Address Space Identifier
+ uint8_t tl; // Trap Level
+ uint64_t tpc[MaxTL]; // Trap Program Counter (value from previous trap level)
+ uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from previous trap level)
+ union
+ {
+ uint64_t tstate[MaxTL]; // Trap State
+ struct
+ {
+ //Values are from previous trap level
+ uint64_t cwp:5; // Current Window Pointer
+ const uint64_t :2; // Reserved bits
+ uint64_t pstate:10; // Process State
+ const uint64_t :6; // Reserved bits
+ uint64_t asi:8; // Address Space Identifier
+ uint64_t ccr:8; // Condition Code Register
+ } tstateFields[MaxTL];
+ }
+ union
+ {
+ uint64_t tick; // Hardware clock-tick counter
+ struct
+ {
+ uint64_t counter:63; // Clock-tick count
+ uint64_t npt:1; // Non-priveleged trap
+ } tickFields;
+ }
+ uint8_t cansave; // Savable windows
+ uint8_t canrestore; // Restorable windows
+ uint8_t otherwin; // Other windows
+ uint8_t cleanwin; // Clean windows
+ union
+ {
+ uint8_t wstate; // Window State
+ struct
+ {
+ uint8_t normal:3; // Bits TT<4:2> are set to on a normal
+ // register window trap
+ uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin"
+ // register window trap
+ } wstateFields;
+ }
+ union
+ {
+ uint64_t ver; // Version
+ struct
+ {
+ uint64_t maxwin:5; // Max CWP value
+ const uint64_t :2; // Reserved bits
+ uint64_t maxtl:8; // Maximum trap level
+ const uint64_t :8; // Reserved bits
+ uint64_t mask:8; // Processor mask set revision number
+ uint64_t impl:16; // Implementation identification number
+ uint64_t manuf:16; // Manufacturer code
+ } verFields;
+ }
+ union
+ {
+ uint64_t fsr; // Floating-Point State Register
+ struct
+ {
+ union
+ {
+ uint64_t cexc:5; // Current excpetion
+ struct
+ {
+ uint64_t nxc:1; // Inexact
+ uint64_t dzc:1; // Divide by zero
+ uint64_t ufc:1; // Underflow
+ uint64_t ofc:1; // Overflow
+ uint64_t nvc:1; // Invalid operand
+ } cexecFields:5;
+ } :5;
+ union
+ {
+ uint64_t aexc:5; // Accrued exception
+ struct
+ {
+ uint64_t nxc:1; // Inexact
+ uint64_t dzc:1; // Divide by zero
+ uint64_t ufc:1; // Underflow
+ uint64_t ofc:1; // Overflow
+ uint64_t nvc:1; // Invalid operand
+ } aexecFields:5;
+ } :5;
+ uint64_t fcc0:2; // Floating-Point condtion codes
+ const uint64_t :1; // Reserved bits
+ uint64_t qne:1; // Deferred trap queue not empty
+ // with no queue, it should read 0
+ uint64_t ftt:3; // Floating-Point trap type
+ uint64_t ver:3; // Version (of the FPU)
+ const uint64_t :2; // Reserved bits
+ uint64_t ns:1; // Nonstandard floating point
+ union
+ {
+ uint64_t tem:5; // Trap Enable Mask
+ struct
+ {
+ uint64_t nxm:1; // Inexact
+ uint64_t dzm:1; // Divide by zero
+ uint64_t ufm:1; // Underflow
+ uint64_t ofm:1; // Overflow
+ uint64_t nvm:1; // Invalid operand
+ } temFields:5;
+ } :5;
+ const uint64_t :2; // Reserved bits
+ uint64_t rd:2; // Rounding direction
+ uint64_t fcc1:2; // Floating-Point condition codes
+ uint64_t fcc2:2; // Floating-Point condition codes
+ uint64_t fcc3:2; // Floating-Point condition codes
+ const uint64_t :26; // Reserved bits
+ } fsrFields;
+ }
+ union
+ {
+ uint8_t fprs; // Floating-Point Register State
+ struct
+ {
+ dl:1; // Dirty lower
+ du:1; // Dirty upper
+ fef:1; // FPRS enable floating-Point
+ } fprsFields;
+ };
+
+ void serialize(std::ostream & os)
+ {
+ SERIALIZE_SCALAR(pstate);
+ SERIAlIZE_SCALAR(tba);
+ SERIALIZE_SCALAR(y);
+ SERIALIZE_SCALAR(pil);
+ SERIALIZE_SCALAR(cwp);
+ SERIALIZE_ARRAY(tt, MaxTL);
+ SERIALIZE_SCALAR(ccr);
+ SERIALIZE_SCALAR(asi);
+ SERIALIZE_SCALAR(tl);
+ SERIALIZE_SCALAR(tpc);
+ SERIALIZE_SCALAR(tnpc);
+ SERIALIZE_ARRAY(tstate, MaxTL);
+ SERIALIZE_SCALAR(tick);
+ SERIALIZE_SCALAR(cansave);
+ SERIALIZE_SCALAR(canrestore);
+ SERIALIZE_SCALAR(otherwin);
+ SERIALIZE_SCALAR(cleanwin);
+ SERIALIZE_SCALAR(wstate);
+ SERIALIZE_SCALAR(ver);
+ SERIALIZE_SCALAR(fsr);
+ SERIALIZE_SCALAR(fprs);
+ }
+
+ void unserialize(Checkpoint &* cp, std::string & section)
+ {
+ UNSERIALIZE_SCALAR(pstate);
+ UNSERIAlIZE_SCALAR(tba);
+ UNSERIALIZE_SCALAR(y);
+ UNSERIALIZE_SCALAR(pil);
+ UNSERIALIZE_SCALAR(cwp);
+ UNSERIALIZE_ARRAY(tt, MaxTL);
+ UNSERIALIZE_SCALAR(ccr);
+ UNSERIALIZE_SCALAR(asi);
+ UNSERIALIZE_SCALAR(tl);
+ UNSERIALIZE_SCALAR(tpc);
+ UNSERIALIZE_SCALAR(tnpc);
+ UNSERIALIZE_ARRAY(tstate, MaxTL);
+ UNSERIALIZE_SCALAR(tick);
+ UNSERIALIZE_SCALAR(cansave);
+ UNSERIALIZE_SCALAR(canrestore);
+ UNSERIALIZE_SCALAR(otherwin);
+ UNSERIALIZE_SCALAR(cleanwin);
+ UNSERIALIZE_SCALAR(wstate);
+ UNSERIALIZE_SCALAR(ver);
+ UNSERIALIZE_SCALAR(fsr);
+ UNSERIALIZE_SCALAR(fprs);
+ }
+ };
+
+ typedef union
+ {
+ IntReg intreg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ struct RegFile
+ {
+ IntRegFile intRegFile; // (signed) integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegFile; // control register file
+
+ Addr pc; // Program Counter
+ Addr npc; // Next Program Counter
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ static StaticInstPtr<AlphaISA> decodeInst(MachInst);
+
+ // return a no-op instruction... used for instruction fetch faults
+ static const MachInst NoopMachInst;
+
+ // Instruction address compression hooks
+ static inline Addr realPCToFetchPC(const Addr &addr)
+ {
+ return addr;
+ }
+
+ static inline Addr fetchPCToRealPC(const Addr &addr)
+ {
+ return addr;
+ }
+
+ // the size of "fetched" instructions (not necessarily the size
+ // of real instructions for PISA)
+ static inline size_t fetchInstSize()
+ {
+ return sizeof(MachInst);
+ }
+
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param xc The execution context.
+ */
+ template <class XC>
+ static void zeroRegisters(XC *xc);
+};
+
+
+typedef SPARCISA 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 VMPageSize = TheISA::VMPageSize;
+const int LogVMPageSize = TheISA::LogVMPageSize;
+const int ZeroReg = TheISA::ZeroReg;
+const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
+const int MaxAddr = (Addr)-1;
+
+#ifndef FULL_SYSTEM
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint64_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint64_t)v;
+ }
+
+ ~SyscallReturn() {}
+
+ SyscallReturn& operator=(const SyscallReturn& s) {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
+
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
+
+
+ private:
+ uint64_t retval;
+ bool success;
+};
+
+#endif
+
+
+#ifdef FULL_SYSTEM
+
+#include "arch/alpha/ev5.hh"
+#endif
+
+#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/base/intmath.hh b/base/intmath.hh
index c8b9c5ec5..df0687c62 100644
--- a/base/intmath.hh
+++ b/base/intmath.hh
@@ -145,22 +145,6 @@ floorLog2(long long x)
return floorLog2((unsigned long long)x);
}
-#if defined(__APPLE__)
-inline int
-floorLog2(size_t x)
-{
- assert(x > 0);
- assert(sizeof(size_t) == 4 || sizeof(size_t) == 8);
-
- // It's my hope that this is optimized away?
- if (sizeof(size_t) == 4)
- return floorLog2((uint32_t)x);
- else if (sizeof(size_t) == 8)
- return floorLog2((uint64_t)x);
-
-}
-#endif
-
template <class T>
inline int
ceilLog2(T n)
diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh
index 26d3ef3b0..3c8659e18 100644
--- a/base/loader/object_file.hh
+++ b/base/loader/object_file.hh
@@ -29,7 +29,7 @@
#ifndef __OBJECT_FILE_HH__
#define __OBJECT_FILE_HH__
-#include "targetarch/isa_traits.hh" // for Addr
+#include "arch/isa_traits.hh" // for Addr
class FunctionalMemory;
class SymbolTable;
diff --git a/base/loader/symtab.hh b/base/loader/symtab.hh
index 324fd8b45..ebcda1345 100644
--- a/base/loader/symtab.hh
+++ b/base/loader/symtab.hh
@@ -32,7 +32,7 @@
#include <iosfwd>
#include <map>
-#include "targetarch/isa_traits.hh" // for Addr
+#include "arch/isa_traits.hh" // for Addr
class Checkpoint;
class SymbolTable
diff --git a/base/sched_list.hh b/base/sched_list.hh
index 0e2f3ddcb..f794e3514 100644
--- a/base/sched_list.hh
+++ b/base/sched_list.hh
@@ -30,8 +30,10 @@
#define SCHED_LIST_HH
#include <list>
+#include "base/intmath.hh"
#include "base/misc.hh"
+
// Any types you use this class for must be covered here...
namespace {
void ClearEntry(int &i) { i = 0; };
@@ -80,7 +82,7 @@ SchedList<T>::SchedList(unsigned _size)
size = _size;
// size must be a power of two
- if (size & (size-1)) {
+ if (!isPowerOf2(size)) {
panic("SchedList: size must be a power of two");
}
diff --git a/base/socket.cc b/base/socket.cc
index f33e79426..45a60e7e3 100644
--- a/base/socket.cc
+++ b/base/socket.cc
@@ -93,9 +93,6 @@ ListenSocket::listen(int port, bool reuse)
return true;
}
-#if defined(__APPLE__)
-typedef int socklen_t;
-#endif
// Open a connection. Accept will block, so if you don't want it to,
// make sure a connection is ready before you call accept.
diff --git a/build/SConstruct b/build/SConstruct
index 45461b0af..c552e5639 100644
--- a/build/SConstruct
+++ b/build/SConstruct
@@ -223,7 +223,7 @@ env = conf.Finish()
# value becomes sticky).
sticky_opts = Options(args=ARGUMENTS)
sticky_opts.AddOptions(
- EnumOption('TARGET_ISA', 'Target ISA', 'alpha', ('alpha')),
+ EnumOption('TARGET_ISA', 'Target ISA', 'alpha', ('alpha', 'sparc', 'mips')),
BoolOption('FULL_SYSTEM', 'Full-system support', False),
BoolOption('ALPHA_TLASER',
'Model Alpha TurboLaser platform (vs. Tsunami)', False),
@@ -320,6 +320,10 @@ base_env = env
for build_dir in build_dirs:
# Make a copy of the default environment to use for this config.
env = base_env.Copy()
+
+ # Record what build_dir was in the environment
+ env.Append(BUILD_DIR=build_dir);
+
# Set env according to the build directory config.
sticky_opts.files = []
diff --git a/build/build_options/default/MIPS_SE b/build/build_options/default/MIPS_SE
new file mode 100644
index 000000000..e74e2f69c
--- /dev/null
+++ b/build/build_options/default/MIPS_SE
@@ -0,0 +1,2 @@
+TARGET_ISA = 'mips'
+FULL_SYSTEM = 0
diff --git a/build/build_options/default/SPARC_SE b/build/build_options/default/SPARC_SE
new file mode 100644
index 000000000..3b256fc34
--- /dev/null
+++ b/build/build_options/default/SPARC_SE
@@ -0,0 +1,2 @@
+TARGET_ISA = 'sparc'
+FULL_SYSTEM = 0
diff --git a/cpu/base.hh b/cpu/base.hh
index 4a44ab804..2bd1210d8 100644
--- a/cpu/base.hh
+++ b/cpu/base.hh
@@ -36,7 +36,7 @@
#include "cpu/sampler/sampler.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
#if FULL_SYSTEM
class System;
diff --git a/cpu/base_dyn_inst.cc b/cpu/base_dyn_inst.cc
index d921bd148..59a12f2d0 100644
--- a/cpu/base_dyn_inst.cc
+++ b/cpu/base_dyn_inst.cc
@@ -113,7 +113,7 @@ BaseDynInst<Impl>::initVars()
asid = 0;
// Initialize the fault to be unimplemented opcode.
- fault = Unimplemented_Opcode_Fault;
+ fault = UnimplementedOpcodeFault;
++instcount;
@@ -142,12 +142,12 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
req->asid = asid;
// Prefetches never cause faults.
- fault = No_Fault;
+ fault = NoFault;
// note this is a local, not BaseDynInst::fault
- Fault trans_fault = xc->translateDataReadReq(req);
+ Fault * trans_fault = xc->translateDataReadReq(req);
- if (trans_fault == No_Fault && !(req->flags & UNCACHEABLE)) {
+ if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
// It's a valid address to cacheable space. Record key MemReq
// parameters so we can generate another one just like it for
// the timing access without calling translate() again (which
@@ -188,7 +188,7 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
fault = xc->translateDataWriteReq(req);
- if (fault == No_Fault && !(req->flags & UNCACHEABLE)) {
+ if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
// Record key MemReq parameters so we can generate another one
// just like it for the timing access without calling translate()
// again (which might mess up the TLB).
@@ -208,16 +208,16 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
* @todo Need to find a way to get the cache block size here.
*/
template <class Impl>
-Fault
+Fault *
BaseDynInst<Impl>::copySrcTranslate(Addr src)
{
MemReqPtr req = new MemReq(src, xc, 64);
req->asid = asid;
// translate to physical address
- Fault fault = xc->translateDataReadReq(req);
+ Fault * fault = xc->translateDataReadReq(req);
- if (fault == No_Fault) {
+ if (fault == NoFault) {
xc->copySrcAddr = src;
xc->copySrcPhysAddr = req->paddr;
} else {
@@ -231,7 +231,7 @@ BaseDynInst<Impl>::copySrcTranslate(Addr src)
* @todo Need to find a way to get the cache block size here.
*/
template <class Impl>
-Fault
+Fault *
BaseDynInst<Impl>::copy(Addr dest)
{
uint8_t data[64];
@@ -241,9 +241,9 @@ BaseDynInst<Impl>::copy(Addr dest)
req->asid = asid;
// translate to physical address
- Fault fault = xc->translateDataWriteReq(req);
+ Fault * fault = xc->translateDataWriteReq(req);
- if (fault == No_Fault) {
+ if (fault == NoFault) {
Addr dest_addr = req->paddr;
// Need to read straight from memory since we have more than 8 bytes.
req->paddr = xc->copySrcPhysAddr;
@@ -277,10 +277,10 @@ BaseDynInst<Impl>::dump(std::string &outstring)
#if 0
template <class Impl>
-Fault
+Fault *
BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
{
- Fault fault;
+ Fault * fault;
// check alignments, even speculative this test should always pass
if ((nbytes & nbytes - 1) != 0 || (addr & nbytes - 1) != 0) {
@@ -292,7 +292,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
#if 0
panic("unaligned access. Cycle = %n", curTick);
#endif
- return No_Fault;
+ return NoFault;
}
MemReqPtr req = new MemReq(addr, thread, nbytes);
@@ -303,7 +303,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
case Write:
fault = spec_mem->write(req, (uint8_t *)p);
- if (fault != No_Fault)
+ if (fault != NoFault)
break;
specMemWrite = true;
@@ -325,7 +325,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
break;
default:
- fault = Machine_Check_Fault;
+ fault = MachineCheckFault;
break;
}
diff --git a/cpu/base_dyn_inst.hh b/cpu/base_dyn_inst.hh
index d29257a52..2c91db99c 100644
--- a/cpu/base_dyn_inst.hh
+++ b/cpu/base_dyn_inst.hh
@@ -89,16 +89,16 @@ class BaseDynInst : public FastAlloc, public RefCounted
Trace::InstRecord *traceData;
template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
+ Fault * read(Addr addr, T &data, unsigned flags);
template <class T>
- Fault write(T data, Addr addr, unsigned flags,
+ Fault * write(T data, Addr addr, unsigned flags,
uint64_t *res);
void prefetch(Addr addr, unsigned flags);
void writeHint(Addr addr, int size, unsigned flags);
- Fault copySrcTranslate(Addr src);
- Fault copy(Addr dest);
+ Fault * copySrcTranslate(Addr src);
+ Fault * copy(Addr dest);
/** @todo: Consider making this private. */
public:
@@ -154,7 +154,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
ExecContext *xc;
/** The kind of fault this instruction has generated. */
- Fault fault;
+ Fault * fault;
/** The effective virtual address (lds & stores only). */
Addr effAddr;
@@ -225,7 +225,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
public:
void
- trace_mem(Fault fault, // last fault
+ trace_mem(Fault * fault, // last fault
MemCmd cmd, // last command
Addr addr, // virtual address of access
void *p, // memory accessed
@@ -238,7 +238,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
void dump(std::string &outstring);
/** Returns the fault type. */
- Fault getFault() { return fault; }
+ Fault * getFault() { return fault; }
/** Checks whether or not this instruction has had its branch target
* calculated yet. For now it is not utilized and is hacked to be
@@ -447,7 +447,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
template<class Impl>
template<class T>
-inline Fault
+inline Fault *
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
{
MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
@@ -472,7 +472,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
req->paddr = req->vaddr;
#endif
- if (fault == No_Fault) {
+ if (fault == NoFault) {
fault = cpu->read(req, data, lqIdx);
} else {
// Return a fixed value to keep simulation deterministic even
@@ -490,7 +490,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
template<class Impl>
template<class T>
-inline Fault
+inline Fault *
BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
if (traceData) {
@@ -520,14 +520,14 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
req->paddr = req->vaddr;
#endif
- if (fault == No_Fault) {
+ if (fault == NoFault) {
fault = cpu->write(req, data, sqIdx);
}
if (res) {
// always return some result to keep misspeculated paths
// (which will ignore faults) deterministic
- *res = (fault == No_Fault) ? req->result : 0;
+ *res = (fault == NoFault) ? req->result : 0;
}
return fault;
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index 9bed3ba47..e7facbebb 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -221,7 +221,7 @@ ExecContext::regStats(const string &name)
}
void
-ExecContext::trap(Fault fault)
+ExecContext::trap(Fault * fault)
{
//TheISA::trap(fault); //One possible way to do it...
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index 6f38a6960..7e195af23 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -34,7 +34,8 @@
#include "mem/mem_req.hh"
#include "sim/host.hh"
#include "sim/serialize.hh"
-#include "targetarch/byte_swap.hh"
+#include "arch/isa_traits.hh"
+#include "sim/byteswap.hh"
// forward declaration: see functional_memory.hh
class FunctionalMemory;
@@ -205,17 +206,17 @@ class ExecContext
int getInstAsid() { return regs.instAsid(); }
int getDataAsid() { return regs.dataAsid(); }
- Fault translateInstReq(MemReqPtr &req)
+ Fault * translateInstReq(MemReqPtr &req)
{
return itb->translate(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault * translateDataReadReq(MemReqPtr &req)
{
return dtb->translate(req, false);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault * translateDataWriteReq(MemReqPtr &req)
{
return dtb->translate(req, true);
}
@@ -230,7 +231,7 @@ class ExecContext
int getInstAsid() { return asid; }
int getDataAsid() { return asid; }
- Fault dummyTranslation(MemReqPtr &req)
+ Fault * dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
@@ -239,17 +240,17 @@ class ExecContext
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return No_Fault;
+ return NoFault;
}
- Fault translateInstReq(MemReqPtr &req)
+ Fault * translateInstReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault * translateDataReadReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault * translateDataWriteReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
@@ -257,7 +258,7 @@ class ExecContext
#endif
template <class T>
- Fault read(MemReqPtr &req, T &data)
+ Fault * read(MemReqPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
if (req->flags & LOCKED) {
@@ -267,14 +268,14 @@ class ExecContext
}
#endif
- Fault error;
+ Fault * error;
error = mem->read(req, data);
- data = gtoh(data);
+ data = LittleEndianGuest::gtoh(data);
return error;
}
template <class T>
- Fault write(MemReqPtr &req, T &data)
+ Fault * write(MemReqPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
@@ -300,7 +301,7 @@ class ExecContext
<< "on cpu " << req->xc->cpu_id
<< std::endl;
}
- return No_Fault;
+ return NoFault;
}
else req->xc->storeCondFailures = 0;
}
@@ -319,7 +320,7 @@ class ExecContext
}
#endif
- return mem->write(req, (T)htog(data));
+ return mem->write(req, (T)LittleEndianGuest::htog(data));
}
virtual bool misspeculating();
@@ -332,7 +333,7 @@ class ExecContext
inst = new_inst;
}
- Fault instRead(MemReqPtr &req)
+ Fault * instRead(MemReqPtr &req)
{
return mem->read(req, inst);
}
@@ -411,13 +412,13 @@ class ExecContext
}
#if FULL_SYSTEM
- uint64_t readIpr(int idx, Fault &fault);
- Fault setIpr(int idx, uint64_t val);
+ uint64_t readIpr(int idx, Fault * &fault);
+ Fault * setIpr(int idx, uint64_t val);
int readIntrFlag() { return regs.intrflag; }
void setIntrFlag(int val) { regs.intrflag = val; }
- Fault hwrei();
+ Fault * hwrei();
bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
- void ev5_trap(Fault fault);
+ void ev5_trap(Fault * fault);
bool simPalCheck(int palFunc);
#endif
@@ -427,7 +428,7 @@ class ExecContext
* @todo How to do this properly so it's dependent upon ISA only?
*/
- void trap(Fault fault);
+ void trap(Fault * fault);
#if !FULL_SYSTEM
IntReg getSyscallArg(int i)
diff --git a/cpu/inst_seq.hh b/cpu/inst_seq.hh
index 3239d4d24..8de047af7 100644
--- a/cpu/inst_seq.hh
+++ b/cpu/inst_seq.hh
@@ -32,7 +32,7 @@
// inst sequence type, used to order instructions in the ready list,
// if this rolls over the ready list order temporarily will get messed
// up, but execution will continue and complete correctly
-typedef unsigned long long InstSeqNum;
+typedef uint64_t InstSeqNum;
// inst tag type, used to tag an operation instance in the IQ
typedef unsigned int InstTag;
diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh
index cba57d189..606f9fa0a 100644
--- a/cpu/o3/alpha_cpu.hh
+++ b/cpu/o3/alpha_cpu.hh
@@ -33,6 +33,8 @@
#define __CPU_O3_CPU_ALPHA_FULL_CPU_HH__
#include "cpu/o3/cpu.hh"
+#include "arch/isa_traits.hh"
+#include "sim/byteswap.hh"
template <class Impl>
class AlphaFullCPU : public FullO3CPU<Impl>
@@ -60,23 +62,23 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// void clear_interrupt(int int_num, int index);
// void clear_interrupts();
- Fault translateInstReq(MemReqPtr &req)
+ Fault * translateInstReq(MemReqPtr &req)
{
return itb->translate(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault * translateDataReadReq(MemReqPtr &req)
{
return dtb->translate(req, false);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault * translateDataWriteReq(MemReqPtr &req)
{
return dtb->translate(req, true);
}
#else
- Fault dummyTranslation(MemReqPtr &req)
+ Fault * dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
@@ -85,20 +87,20 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return No_Fault;
+ return NoFault;
}
- Fault translateInstReq(MemReqPtr &req)
+ Fault * translateInstReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault * translateDataReadReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault * translateDataWriteReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
@@ -133,16 +135,16 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// look like.
#if FULL_SYSTEM
uint64_t *getIpr();
- uint64_t readIpr(int idx, Fault &fault);
- Fault setIpr(int idx, uint64_t val);
+ uint64_t readIpr(int idx, Fault * &fault);
+ Fault * setIpr(int idx, uint64_t val);
int readIntrFlag();
void setIntrFlag(int val);
- Fault hwrei();
+ Fault * hwrei();
bool inPalMode() { return AlphaISA::PcPAL(this->regFile.readPC()); }
bool inPalMode(uint64_t PC)
{ return AlphaISA::PcPAL(PC); }
- void trap(Fault fault);
+ void trap(Fault * fault);
bool simPalCheck(int palFunc);
void processInterrupts();
@@ -195,7 +197,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
bool palShadowEnabled;
// Not sure this is used anywhere.
- void intr_post(RegFile *regs, Fault fault, Addr pc);
+ void intr_post(RegFile *regs, Fault * fault, Addr pc);
// Actually used within exec files. Implement properly.
void swapPALShadow(bool use_shadow);
// Called by CPU constructor. Can implement as I please.
@@ -208,7 +210,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
template <class T>
- Fault read(MemReqPtr &req, T &data)
+ Fault * read(MemReqPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
if (req->flags & LOCKED) {
@@ -218,20 +220,20 @@ class AlphaFullCPU : public FullO3CPU<Impl>
}
#endif
- Fault error;
+ Fault * error;
error = this->mem->read(req, data);
data = gtoh(data);
return error;
}
template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx)
+ Fault * read(MemReqPtr &req, T &data, int load_idx)
{
return this->iew.ldstQueue.read(req, data, load_idx);
}
template <class T>
- Fault write(MemReqPtr &req, T &data)
+ Fault * write(MemReqPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
@@ -257,7 +259,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
<< "on cpu " << this->cpu_id
<< std::endl;
}
- return No_Fault;
+ return NoFault;
}
else req->xc->storeCondFailures = 0;
}
@@ -277,11 +279,11 @@ class AlphaFullCPU : public FullO3CPU<Impl>
#endif
- return this->mem->write(req, (T)htog(data));
+ return this->mem->write(req, (T)::htog(data));
}
template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx)
+ Fault * write(MemReqPtr &req, T &data, int store_idx)
{
return this->iew.ldstQueue.write(req, data, store_idx);
}
diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh
index 2a764740b..408676331 100644
--- a/cpu/o3/alpha_cpu_impl.hh
+++ b/cpu/o3/alpha_cpu_impl.hh
@@ -42,9 +42,6 @@
#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/alpha/isa_traits.hh"
-//#include "arch/alpha/ev5.hh"
-
-//using namespace EV5;
#endif
template <class Impl>
@@ -249,13 +246,13 @@ AlphaFullCPU<Impl>::getIpr()
template <class Impl>
uint64_t
-AlphaFullCPU<Impl>::readIpr(int idx, Fault &fault)
+AlphaFullCPU<Impl>::readIpr(int idx, Fault * &fault)
{
return this->regFile.readIpr(idx, fault);
}
template <class Impl>
-Fault
+Fault *
AlphaFullCPU<Impl>::setIpr(int idx, uint64_t val)
{
return this->regFile.setIpr(idx, val);
@@ -277,13 +274,13 @@ AlphaFullCPU<Impl>::setIntrFlag(int val)
// Can force commit stage to squash and stuff.
template <class Impl>
-Fault
+Fault *
AlphaFullCPU<Impl>::hwrei()
{
uint64_t *ipr = getIpr();
if (!inPalMode())
- return Unimplemented_Opcode_Fault;
+ return UnimplementedOpcodeFault;
setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
@@ -295,7 +292,7 @@ AlphaFullCPU<Impl>::hwrei()
this->checkInterrupts = true;
// FIXME: XXX check for interrupts? XXX
- return No_Fault;
+ return NoFault;
}
template <class Impl>
@@ -326,28 +323,28 @@ AlphaFullCPU<Impl>::simPalCheck(int palFunc)
// stage.
template <class Impl>
void
-AlphaFullCPU<Impl>::trap(Fault fault)
+AlphaFullCPU<Impl>::trap(Fault * fault)
{
// Keep in mind that a trap may be initiated by fetch if there's a TLB
// miss
uint64_t PC = this->commit.readCommitPC();
- DPRINTF(Fault, "Fault %s\n", FaultName(fault));
- this->recordEvent(csprintf("Fault %s", FaultName(fault)));
+ DPRINTF(Fault, "Fault %s\n", fault ? fault->name : "name");
+ this->recordEvent(csprintf("Fault %s", fault ? fault->name : "name"));
// kernelStats.fault(fault);
- if (fault == Arithmetic_Fault)
+ if (fault == ArithmeticFault)
panic("Arithmetic traps are unimplemented!");
typename AlphaISA::InternalProcReg *ipr = getIpr();
// exception restart address - Get the commit PC
- if (fault != Interrupt_Fault || !inPalMode(PC))
+ if (fault != InterruptFault || !inPalMode(PC))
ipr[AlphaISA::IPR_EXC_ADDR] = PC;
- if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
- fault == Interrupt_Fault && !PC_PAL(regs.pc) */) {
+ if (fault == PalFault || fault == ArithmeticFault /* ||
+ fault == InterruptFault && !PC_PAL(regs.pc) */) {
// traps... skip faulting instruction
ipr[AlphaISA::IPR_EXC_ADDR] += 4;
}
@@ -356,7 +353,7 @@ AlphaFullCPU<Impl>::trap(Fault fault)
swapPALShadow(true);
this->regFile.setPC( ipr[AlphaISA::IPR_PAL_BASE] +
- AlphaISA::fault_addr[fault] );
+ AlphaISA::fault_addr(fault) );
this->regFile.setNextPC(PC + sizeof(MachInst));
}
diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh
index bb90bf21a..77dcbaf74 100644
--- a/cpu/o3/alpha_dyn_inst.hh
+++ b/cpu/o3/alpha_dyn_inst.hh
@@ -74,7 +74,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst);
/** Executes the instruction.*/
- Fault execute()
+ Fault * execute()
{
return this->fault = this->staticInst->execute(this, this->traceData);
}
@@ -87,13 +87,13 @@ class AlphaDynInst : public BaseDynInst<Impl>
void setFpcr(uint64_t val);
#if FULL_SYSTEM
- uint64_t readIpr(int idx, Fault &fault);
- Fault setIpr(int idx, uint64_t val);
- Fault hwrei();
+ uint64_t readIpr(int idx, Fault * &fault);
+ Fault * setIpr(int idx, uint64_t val);
+ Fault * hwrei();
int readIntrFlag();
void setIntrFlag(int val);
bool inPalMode();
- void trap(Fault fault);
+ void trap(Fault * fault);
bool simPalCheck(int palFunc);
#else
void syscall();
@@ -220,12 +220,12 @@ class AlphaDynInst : public BaseDynInst<Impl>
}
public:
- Fault calcEA()
+ Fault * calcEA()
{
return this->staticInst->eaCompInst()->execute(this, this->traceData);
}
- Fault memAccess()
+ Fault * memAccess()
{
return this->staticInst->memAccInst()->execute(this, this->traceData);
}
diff --git a/cpu/o3/alpha_dyn_inst_impl.hh b/cpu/o3/alpha_dyn_inst_impl.hh
index d1ebb812d..b20af48cd 100644
--- a/cpu/o3/alpha_dyn_inst_impl.hh
+++ b/cpu/o3/alpha_dyn_inst_impl.hh
@@ -98,20 +98,20 @@ AlphaDynInst<Impl>::setFpcr(uint64_t val)
#if FULL_SYSTEM
template <class Impl>
uint64_t
-AlphaDynInst<Impl>::readIpr(int idx, Fault &fault)
+AlphaDynInst<Impl>::readIpr(int idx, Fault * &fault)
{
return this->cpu->readIpr(idx, fault);
}
template <class Impl>
-Fault
+Fault *
AlphaDynInst<Impl>::setIpr(int idx, uint64_t val)
{
return this->cpu->setIpr(idx, val);
}
template <class Impl>
-Fault
+Fault *
AlphaDynInst<Impl>::hwrei()
{
return this->cpu->hwrei();
@@ -140,7 +140,7 @@ AlphaDynInst<Impl>::inPalMode()
template <class Impl>
void
-AlphaDynInst<Impl>::trap(Fault fault)
+AlphaDynInst<Impl>::trap(Fault * fault)
{
this->cpu->trap(fault);
}
diff --git a/cpu/o3/commit_impl.hh b/cpu/o3/commit_impl.hh
index dc0986772..47b4dfd00 100644
--- a/cpu/o3/commit_impl.hh
+++ b/cpu/o3/commit_impl.hh
@@ -393,9 +393,9 @@ SimpleCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
}
// Check if the instruction caused a fault. If so, trap.
- Fault inst_fault = head_inst->getFault();
+ Fault * inst_fault = head_inst->getFault();
- if (inst_fault != No_Fault && inst_fault != Fake_Mem_Fault) {
+ if (inst_fault != NoFault) {
if (!head_inst->isNop()) {
#if FULL_SYSTEM
cpu->trap(inst_fault);
diff --git a/cpu/o3/fetch.hh b/cpu/o3/fetch.hh
index 24e445f0b..5443d274e 100644
--- a/cpu/o3/fetch.hh
+++ b/cpu/o3/fetch.hh
@@ -123,7 +123,7 @@ class SimpleFetch
* @param fetch_PC The PC address that is being fetched from.
* @return Any fault that occured.
*/
- Fault fetchCacheLine(Addr fetch_PC);
+ Fault * fetchCacheLine(Addr fetch_PC);
inline void doSquash(const Addr &new_PC);
diff --git a/cpu/o3/fetch_impl.hh b/cpu/o3/fetch_impl.hh
index c943fd36a..e8d333ed4 100644
--- a/cpu/o3/fetch_impl.hh
+++ b/cpu/o3/fetch_impl.hh
@@ -29,8 +29,8 @@
// Remove this later; used only for debugging.
#define OPCODE(X) (X >> 26) & 0x3f
-
-#include "arch/alpha/byte_swap.hh"
+#include "arch/isa_traits.hh"
+#include "sim/byteswap.hh"
#include "cpu/exetrace.hh"
#include "mem/base_mem.hh"
#include "mem/mem_interface.hh"
@@ -221,7 +221,7 @@ SimpleFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC)
}
template <class Impl>
-Fault
+Fault *
SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
{
// Check if the instruction exists within the cache.
@@ -236,7 +236,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
unsigned flags = 0;
#endif // FULL_SYSTEM
- Fault fault = No_Fault;
+ Fault * fault = NoFault;
// Align the fetch PC so it's at the start of a cache block.
fetch_PC = icacheBlockAlignPC(fetch_PC);
@@ -258,7 +258,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
// If translation was successful, attempt to read the first
// instruction.
- if (fault == No_Fault) {
+ if (fault == NoFault) {
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
fault = cpu->mem->read(memReq, cacheData);
// This read may change when the mem interface changes.
@@ -268,7 +268,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
// Now do the timing access to see whether or not the instruction
// exists within the cache.
- if (icacheInterface && fault == No_Fault) {
+ if (icacheInterface && fault == NoFault) {
DPRINTF(Fetch, "Fetch: Doing timing memory access.\n");
memReq->completionEvent = NULL;
@@ -468,7 +468,7 @@ SimpleFetch<Impl>::fetch()
Addr fetch_PC = cpu->readPC();
// Fault code for memory access.
- Fault fault = No_Fault;
+ Fault * fault = NoFault;
// If returning from the delay of a cache miss, then update the status
// to running, otherwise do the cache access. Possibly move this up
@@ -506,7 +506,7 @@ SimpleFetch<Impl>::fetch()
unsigned offset = fetch_PC & cacheBlkMask;
unsigned fetched;
- if (fault == No_Fault) {
+ if (fault == NoFault) {
// If the read of the first instruction was successful, then grab the
// instructions from the rest of the cache line and put them into the
// queue heading to decode.
@@ -582,7 +582,7 @@ SimpleFetch<Impl>::fetch()
// Or might want to leave setting the PC to the main CPU, with fetch
// only changing the nextPC (will require correct determination of
// next PC).
- if (fault == No_Fault) {
+ if (fault == NoFault) {
DPRINTF(Fetch, "Fetch: Setting PC to %08p.\n", next_PC);
cpu->setPC(next_PC);
cpu->setNextPC(next_PC + instSize);
diff --git a/cpu/o3/inst_queue_impl.hh b/cpu/o3/inst_queue_impl.hh
index 2221ba456..048dc7c00 100644
--- a/cpu/o3/inst_queue_impl.hh
+++ b/cpu/o3/inst_queue_impl.hh
@@ -34,6 +34,7 @@
// but probably is more flexible to actually add in a delay parameter than
// just running it backwards.
+#include <limits>
#include <vector>
#include "sim/root.hh"
@@ -42,7 +43,7 @@
// Either compile error or max int due to sign extension.
// Hack to avoid compile warnings.
-const InstSeqNum MaxInstSeqNum = 0 - 1;
+const InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max();
template <class Impl>
InstructionQueue<Impl>::InstructionQueue(Params &params)
diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh
index 4d47b8f9c..5aafd5495 100644
--- a/cpu/o3/regfile.hh
+++ b/cpu/o3/regfile.hh
@@ -32,6 +32,7 @@
// @todo: Destructor
#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/faults.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/o3/comm.hh"
@@ -211,8 +212,8 @@ class PhysRegFile
}
#if FULL_SYSTEM
- uint64_t readIpr(int idx, Fault &fault);
- Fault setIpr(int idx, uint64_t val);
+ uint64_t readIpr(int idx, Fault * &fault);
+ Fault * setIpr(int idx, uint64_t val);
InternalProcReg *getIpr() { return ipr; }
int readIntrFlag() { return intrflag; }
void setIntrFlag(int val) { intrflag = val; }
@@ -275,7 +276,7 @@ PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
//the DynInst level.
template <class Impl>
uint64_t
-PhysRegFile<Impl>::readIpr(int idx, Fault &fault)
+PhysRegFile<Impl>::readIpr(int idx, Fault * &fault)
{
uint64_t retval = 0; // return value, default 0
@@ -368,12 +369,12 @@ PhysRegFile<Impl>::readIpr(int idx, Fault &fault)
case ISA::IPR_DTB_IAP:
case ISA::IPR_ITB_IA:
case ISA::IPR_ITB_IAP:
- fault = Unimplemented_Opcode_Fault;
+ fault = UnimplementedOpcodeFault;
break;
default:
// invalid IPR
- fault = Unimplemented_Opcode_Fault;
+ fault = UnimplementedOpcodeFault;
break;
}
@@ -383,7 +384,7 @@ PhysRegFile<Impl>::readIpr(int idx, Fault &fault)
extern int break_ipl;
template <class Impl>
-Fault
+Fault *
PhysRegFile<Impl>::setIpr(int idx, uint64_t val)
{
uint64_t old;
@@ -521,7 +522,7 @@ PhysRegFile<Impl>::setIpr(int idx, uint64_t val)
case ISA::IPR_ITB_PTE_TEMP:
case ISA::IPR_DTB_PTE_TEMP:
// read-only registers
- return Unimplemented_Opcode_Fault;
+ return UnimplementedOpcodeFault;
case ISA::IPR_HWINT_CLR:
case ISA::IPR_SL_XMIT:
@@ -623,11 +624,11 @@ PhysRegFile<Impl>::setIpr(int idx, uint64_t val)
default:
// invalid IPR
- return Unimplemented_Opcode_Fault;
+ return UnimplementedOpcodeFault;
}
// no error...
- return No_Fault;
+ return NoFault;
}
#endif // #if FULL_SYSTEM
diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh
index 5af77862a..21fe05b6a 100644
--- a/cpu/ozone/cpu.hh
+++ b/cpu/ozone/cpu.hh
@@ -286,17 +286,17 @@ class OoOCPU : public BaseCPU
int getInstAsid() { return xc->regs.instAsid(); }
int getDataAsid() { return xc->regs.dataAsid(); }
- Fault translateInstReq(MemReqPtr &req)
+ Fault * translateInstReq(MemReqPtr &req)
{
return itb->translate(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault * translateDataReadReq(MemReqPtr &req)
{
return dtb->translate(req, false);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault * translateDataWriteReq(MemReqPtr &req)
{
return dtb->translate(req, true);
}
@@ -311,7 +311,7 @@ class OoOCPU : public BaseCPU
int getInstAsid() { return xc->asid; }
int getDataAsid() { return xc->asid; }
- Fault dummyTranslation(MemReqPtr &req)
+ Fault * dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
@@ -320,17 +320,17 @@ class OoOCPU : public BaseCPU
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return No_Fault;
+ return NoFault;
}
- Fault translateInstReq(MemReqPtr &req)
+ Fault * translateInstReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault * translateDataReadReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault * translateDataWriteReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
@@ -338,10 +338,10 @@ class OoOCPU : public BaseCPU
#endif
template <class T>
- Fault read(Addr addr, T &data, unsigned flags, DynInstPtr inst);
+ Fault * read(Addr addr, T &data, unsigned flags, DynInstPtr inst);
template <class T>
- Fault write(T data, Addr addr, unsigned flags,
+ Fault * write(T data, Addr addr, unsigned flags,
uint64_t *res, DynInstPtr inst);
void prefetch(Addr addr, unsigned flags)
@@ -354,9 +354,9 @@ class OoOCPU : public BaseCPU
// need to do this...
}
- Fault copySrcTranslate(Addr src);
+ Fault * copySrcTranslate(Addr src);
- Fault copy(Addr dest);
+ Fault * copy(Addr dest);
private:
bool executeInst(DynInstPtr &inst);
@@ -369,7 +369,7 @@ class OoOCPU : public BaseCPU
bool getOneInst();
- Fault fetchCacheLine();
+ Fault * fetchCacheLine();
InstSeqNum getAndIncrementInstSeq();
@@ -512,13 +512,13 @@ class OoOCPU : public BaseCPU
void setFpcr(uint64_t val) { xc->setFpcr(val); }
#if FULL_SYSTEM
- uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
- Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
- Fault hwrei() { return xc->hwrei(); }
+ uint64_t readIpr(int idx, Fault * &fault) { return xc->readIpr(idx, fault); }
+ Fault * setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
+ Fault * hwrei() { return xc->hwrei(); }
int readIntrFlag() { return xc->readIntrFlag(); }
void setIntrFlag(int val) { xc->setIntrFlag(val); }
bool inPalMode() { return xc->inPalMode(); }
- void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
+ void ev5_trap(Fault * fault) { xc->ev5_trap(fault); }
bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
void syscall() { xc->syscall(); }
@@ -531,7 +531,7 @@ class OoOCPU : public BaseCPU
// precise architected memory state accessor macros
template <class Impl>
template <class T>
-Fault
+Fault *
OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst)
{
MemReqPtr readReq = new MemReq();
@@ -542,21 +542,21 @@ OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst)
readReq->reset(addr, sizeof(T), flags);
// translate to physical address - This might be an ISA impl call
- Fault fault = translateDataReadReq(readReq);
+ Fault * fault = translateDataReadReq(readReq);
// do functional access
- if (fault == No_Fault)
+ if (fault == NoFault)
fault = xc->mem->read(readReq, data);
#if 0
if (traceData) {
traceData->setAddr(addr);
- if (fault == No_Fault)
+ if (fault == NoFault)
traceData->setData(data);
}
#endif
// if we have a cache, do cache access too
- if (fault == No_Fault && dcacheInterface) {
+ if (fault == NoFault && dcacheInterface) {
readReq->cmd = Read;
readReq->completionEvent = NULL;
readReq->time = curTick;
@@ -576,7 +576,7 @@ OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst)
template <class Impl>
template <class T>
-Fault
+Fault *
OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
uint64_t *res, DynInstPtr inst)
{
@@ -595,13 +595,13 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
writeReq->reset(addr, sizeof(T), flags);
// translate to physical address
- Fault fault = translateDataWriteReq(writeReq);
+ Fault * fault = translateDataWriteReq(writeReq);
// do functional access
- if (fault == No_Fault)
+ if (fault == NoFault)
fault = xc->write(writeReq, data);
- if (fault == No_Fault && dcacheInterface) {
+ if (fault == NoFault && dcacheInterface) {
writeReq->cmd = Write;
memcpy(writeReq->data,(uint8_t *)&data,writeReq->size);
writeReq->completionEvent = NULL;
@@ -614,7 +614,7 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
}
}
- if (res && (fault == No_Fault))
+ if (res && (fault == NoFault))
*res = writeReq->result;
if (!dcacheInterface && (writeReq->flags & UNCACHEABLE))
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
index a7f4fa499..6aff94abd 100644
--- a/cpu/simple/cpu.cc
+++ b/cpu/simple/cpu.cc
@@ -54,6 +54,7 @@
#include "kern/kernel_stats.hh"
#include "mem/base_mem.hh"
#include "mem/mem_interface.hh"
+#include "sim/byteswap.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
@@ -74,6 +75,8 @@
#endif // FULL_SYSTEM
using namespace std;
+//The SimpleCPU does alpha only
+using namespace LittleEndianGuest;
SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
@@ -309,7 +312,7 @@ change_thread_state(int thread_number, int activate, int priority)
{
}
-Fault
+Fault *
SimpleCPU::copySrcTranslate(Addr src)
{
static bool no_warn = true;
@@ -329,11 +332,11 @@ SimpleCPU::copySrcTranslate(Addr src)
memReq->reset(src & ~(blk_size - 1), blk_size);
// translate to physical address
- Fault fault = xc->translateDataReadReq(memReq);
+ Fault * fault = xc->translateDataReadReq(memReq);
- assert(fault != Alignment_Fault);
+ assert(fault != AlignmentFault);
- if (fault == No_Fault) {
+ if (fault == NoFault) {
xc->copySrcAddr = src;
xc->copySrcPhysAddr = memReq->paddr + offset;
} else {
@@ -343,7 +346,7 @@ SimpleCPU::copySrcTranslate(Addr src)
return fault;
}
-Fault
+Fault *
SimpleCPU::copy(Addr dest)
{
static bool no_warn = true;
@@ -364,11 +367,11 @@ SimpleCPU::copy(Addr dest)
memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
- Fault fault = xc->translateDataWriteReq(memReq);
+ Fault * fault = xc->translateDataWriteReq(memReq);
- assert(fault != Alignment_Fault);
+ assert(fault != AlignmentFault);
- if (fault == No_Fault) {
+ if (fault == NoFault) {
Addr dest_addr = memReq->paddr + offset;
// Need to read straight from memory since we have more than 8 bytes.
memReq->paddr = xc->copySrcPhysAddr;
@@ -391,11 +394,11 @@ SimpleCPU::copy(Addr dest)
// precise architected memory state accessor macros
template <class T>
-Fault
+Fault *
SimpleCPU::read(Addr addr, T &data, unsigned flags)
{
if (status() == DcacheMissStall || status() == DcacheMissSwitch) {
- Fault fault = xc->read(memReq,data);
+ Fault * fault = xc->read(memReq,data);
if (traceData) {
traceData->setAddr(addr);
@@ -406,10 +409,10 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
- Fault fault = xc->translateDataReadReq(memReq);
+ Fault * fault = xc->translateDataReadReq(memReq);
// if we have a cache, do cache access too
- if (fault == No_Fault && dcacheInterface) {
+ if (fault == NoFault && dcacheInterface) {
memReq->cmd = Read;
memReq->completionEvent = NULL;
memReq->time = curTick;
@@ -429,7 +432,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
fault = xc->read(memReq, data);
}
- } else if(fault == No_Fault) {
+ } else if(fault == NoFault) {
// do functional access
fault = xc->read(memReq, data);
@@ -444,32 +447,32 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
-Fault
+Fault *
SimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
template
-Fault
+Fault *
SimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
template
-Fault
+Fault *
SimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
template
-Fault
+Fault *
SimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
#endif //DOXYGEN_SHOULD_SKIP_THIS
template<>
-Fault
+Fault *
SimpleCPU::read(Addr addr, double &data, unsigned flags)
{
return read(addr, *(uint64_t*)&data, flags);
}
template<>
-Fault
+Fault *
SimpleCPU::read(Addr addr, float &data, unsigned flags)
{
return read(addr, *(uint32_t*)&data, flags);
@@ -477,7 +480,7 @@ SimpleCPU::read(Addr addr, float &data, unsigned flags)
template<>
-Fault
+Fault *
SimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
{
return read(addr, (uint32_t&)data, flags);
@@ -485,19 +488,19 @@ SimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
template <class T>
-Fault
+Fault *
SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
- Fault fault = xc->translateDataWriteReq(memReq);
+ Fault * fault = xc->translateDataWriteReq(memReq);
// do functional access
- if (fault == No_Fault)
+ if (fault == NoFault)
fault = xc->write(memReq, data);
- if (fault == No_Fault && dcacheInterface) {
+ if (fault == NoFault && dcacheInterface) {
memReq->cmd = Write;
memcpy(memReq->data,(uint8_t *)&data,memReq->size);
memReq->completionEvent = NULL;
@@ -516,7 +519,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
}
}
- if (res && (fault == No_Fault))
+ if (res && (fault == NoFault))
*res = memReq->result;
if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
@@ -528,32 +531,32 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
-Fault
+Fault *
SimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
template
-Fault
+Fault *
SimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
template
-Fault
+Fault *
SimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
template
-Fault
+Fault *
SimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
#endif //DOXYGEN_SHOULD_SKIP_THIS
template<>
-Fault
+Fault *
SimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
{
return write(*(uint64_t*)&data, addr, flags, res);
}
template<>
-Fault
+Fault *
SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
{
return write(*(uint32_t*)&data, addr, flags, res);
@@ -561,7 +564,7 @@ SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
template<>
-Fault
+Fault *
SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
{
return write((uint32_t)data, addr, flags, res);
@@ -635,7 +638,7 @@ SimpleCPU::tick()
traceData = NULL;
- Fault fault = No_Fault;
+ Fault * fault = NoFault;
#if FULL_SYSTEM
if (checkInterrupts && check_interrupts() && !xc->inPalMode() &&
@@ -672,7 +675,7 @@ SimpleCPU::tick()
if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) {
ipr[TheISA::IPR_ISR] = summary;
ipr[TheISA::IPR_INTID] = ipl;
- xc->ev5_trap(Interrupt_Fault);
+ xc->ev5_trap(InterruptFault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
ipr[TheISA::IPR_IPLR], ipl, summary);
@@ -710,10 +713,10 @@ SimpleCPU::tick()
fault = xc->translateInstReq(memReq);
- if (fault == No_Fault)
+ if (fault == NoFault)
fault = xc->mem->read(memReq, inst);
- if (icacheInterface && fault == No_Fault) {
+ if (icacheInterface && fault == NoFault) {
memReq->completionEvent = NULL;
memReq->time = curTick;
@@ -735,7 +738,7 @@ SimpleCPU::tick()
// If we've got a valid instruction (i.e., no fault on instruction
// fetch), then execute it.
- if (fault == No_Fault) {
+ if (fault == NoFault) {
// keep an instruction count
numInst++;
@@ -792,9 +795,9 @@ SimpleCPU::tick()
traceFunctions(xc->regs.pc);
- } // if (fault == No_Fault)
+ } // if (fault == NoFault)
- if (fault != No_Fault) {
+ if (fault != NoFault) {
#if FULL_SYSTEM
xc->ev5_trap(fault);
#else // !FULL_SYSTEM
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
index 0f7251237..e7a447117 100644
--- a/cpu/simple/cpu.hh
+++ b/cpu/simple/cpu.hh
@@ -234,10 +234,10 @@ class SimpleCPU : public BaseCPU
virtual void unserialize(Checkpoint *cp, const std::string &section);
template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
+ Fault * read(Addr addr, T &data, unsigned flags);
template <class T>
- Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
+ Fault * write(T data, Addr addr, unsigned flags, uint64_t *res);
// These functions are only used in CPU models that split
// effective address computation from the actual memory access.
@@ -254,9 +254,9 @@ class SimpleCPU : public BaseCPU
// need to do this...
}
- Fault copySrcTranslate(Addr src);
+ Fault * copySrcTranslate(Addr src);
- Fault copy(Addr dest);
+ Fault * copy(Addr dest);
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
@@ -325,13 +325,13 @@ class SimpleCPU : public BaseCPU
void setFpcr(uint64_t val) { xc->setFpcr(val); }
#if FULL_SYSTEM
- uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
- Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
- Fault hwrei() { return xc->hwrei(); }
+ uint64_t readIpr(int idx, Fault * &fault) { return xc->readIpr(idx, fault); }
+ Fault * setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
+ Fault * hwrei() { return xc->hwrei(); }
int readIntrFlag() { return xc->readIntrFlag(); }
void setIntrFlag(int val) { xc->setIntrFlag(val); }
bool inPalMode() { return xc->inPalMode(); }
- void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
+ void ev5_trap(Fault * fault) { xc->ev5_trap(fault); }
bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
void syscall() { xc->syscall(); }
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 85cfb5ae7..24997eadc 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -36,7 +36,7 @@
#include "base/refcnt.hh"
#include "encumbered/cpu/full/op_class.hh"
#include "sim/host.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
// forward declarations
struct AlphaSimpleImpl;
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 61b444628..38fbbdef0 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -99,7 +99,7 @@ AlphaConsole::startup()
alphaAccess->intrClockFrequency = platform->intrFrequency();
}
-Fault
+Fault *
AlphaConsole::read(MemReqPtr &req, uint8_t *data)
{
memset(data, 0, req->size);
@@ -183,13 +183,13 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data)
}
break;
default:
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
{
uint64_t val;
@@ -203,7 +203,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
val = *(uint64_t *)data;
break;
default:
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
@@ -256,10 +256,10 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
break;
default:
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
- return No_Fault;
+ return NoFault;
}
Tick
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index 74ad795f0..75f0a3a67 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -110,8 +110,8 @@ class AlphaConsole : public PioDevice
/**
* memory mapped reads and writes
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* standard serialization routines for checkpointing
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 52c538707..b6ca919e4 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -61,19 +61,19 @@ BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
}
-Fault
+Fault *
BadDevice::read(MemReqPtr &req, uint8_t *data)
{
panic("Device %s not imlpmented\n", devname);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
BadDevice::write(MemReqPtr &req, const uint8_t *data)
{
panic("Device %s not imlpmented\n", devname);
- return No_Fault;
+ return NoFault;
}
Tick
diff --git a/dev/baddev.hh b/dev/baddev.hh
index c2a204c05..b7b67e31a 100644
--- a/dev/baddev.hh
+++ b/dev/baddev.hh
@@ -71,7 +71,7 @@ class BadDevice : public PioDevice
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
* On a write event we just panic aand hopefully print a
@@ -80,7 +80,7 @@ class BadDevice : public PioDevice
* @param data The data to write.
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* Return how long this access will take.
diff --git a/dev/disk_image.cc b/dev/disk_image.cc
index 106723c55..447c54697 100644
--- a/dev/disk_image.cc
+++ b/dev/disk_image.cc
@@ -46,7 +46,7 @@
#include "dev/disk_image.hh"
#include "sim/builder.hh"
#include "sim/sim_exit.hh"
-#include "targetarch/byte_swap.hh"
+#include "sim/byteswap.hh"
using namespace std;
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index 1279efc82..a5cb0dfd8 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -390,7 +390,7 @@ IdeController::writeConfig(int offset, int size, const uint8_t *data)
}
}
-Fault
+Fault *
IdeController::read(MemReqPtr &req, uint8_t *data)
{
Addr offset;
@@ -401,7 +401,7 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
parseAddr(req->paddr, offset, channel, reg_type);
if (!io_enabled)
- return No_Fault;
+ return NoFault;
switch (reg_type) {
case BMI_BLOCK:
@@ -457,10 +457,10 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
offset, req->size, *(uint32_t*)data);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
IdeController::write(MemReqPtr &req, const uint8_t *data)
{
Addr offset;
@@ -472,12 +472,12 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
parseAddr(req->paddr, offset, channel, reg_type);
if (!io_enabled)
- return No_Fault;
+ return NoFault;
switch (reg_type) {
case BMI_BLOCK:
if (!bm_enabled)
- return No_Fault;
+ return NoFault;
switch (offset) {
// Bus master IDE command register
@@ -627,7 +627,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
offset, req->size, *(uint32_t*)data);
- return No_Fault;
+ return NoFault;
}
////
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index 0fbaf9207..72523f57c 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -213,7 +213,7 @@ class IdeController : public PciDev
* @param data Return the field read.
* @return The fault condition of the access.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
* Write to the mmapped I/O control registers.
@@ -221,7 +221,7 @@ class IdeController : public PciDev
* @param data The data to write.
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* Serialize this object to the given output stream.
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index ea8f151c0..9d8bb8825 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -50,7 +50,7 @@
#include "sim/builder.hh"
#include "sim/sim_object.hh"
#include "sim/root.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
using namespace std;
diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc
index e2802eaa9..93c9eedbf 100644
--- a/dev/isa_fake.cc
+++ b/dev/isa_fake.cc
@@ -59,7 +59,7 @@ IsaFake::IsaFake(const string &name, Addr a, MemoryController *mmu,
}
}
-Fault
+Fault *
IsaFake::read(MemReqPtr &req, uint8_t *data)
{
DPRINTF(Tsunami, "read va=%#x size=%d\n",
@@ -73,26 +73,26 @@ IsaFake::read(MemReqPtr &req, uint8_t *data)
case sizeof(uint64_t):
*(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL;
- return No_Fault;
+ return NoFault;
case sizeof(uint32_t):
*(uint32_t*)data = 0xFFFFFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint16_t):
*(uint16_t*)data = 0xFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint8_t):
*(uint8_t*)data = 0xFF;
- return No_Fault;
+ return NoFault;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
DPRINTFN("Isa FakeSMC ERROR: read daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
IsaFake::write(MemReqPtr &req, const uint8_t *data)
{
DPRINTF(Tsunami, "write - va=%#x size=%d \n",
@@ -100,7 +100,7 @@ IsaFake::write(MemReqPtr &req, const uint8_t *data)
//:Addr daddr = (req->paddr & addr_mask) >> 6;
- return No_Fault;
+ return NoFault;
}
Tick
diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh
index 290b24b54..60ca5f90a 100644
--- a/dev/isa_fake.hh
+++ b/dev/isa_fake.hh
@@ -65,14 +65,14 @@ class IsaFake : public PioDevice
* @param req The memory request.
* @param data Where to put the data.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
* All writes are simply ignored.
* @param req The memory request.
* @param data the data to not write.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* Return how long this access will take.
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index 9010850ab..c28615438 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -558,7 +558,7 @@ NSGigE::writeConfig(int offset, int size, const uint8_t* data)
* This reads the device registers, which are detailed in the NS83820
* spec sheet
*/
-Fault
+Fault *
NSGigE::read(MemReqPtr &req, uint8_t *data)
{
assert(ioEnable);
@@ -575,14 +575,14 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
readConfig(daddr & 0xff, req->size, data);
- return No_Fault;
+ return NoFault;
} else if (daddr >= MIB_START && daddr <= MIB_END) {
// don't implement all the MIB's. hopefully the kernel
// doesn't actually DEPEND upon their values
// MIB are just hardware stats keepers
uint32_t &reg = *(uint32_t *) data;
reg = 0;
- return No_Fault;
+ return NoFault;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
@@ -784,10 +784,10 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
daddr, req->size);
}
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
NSGigE::write(MemReqPtr &req, const uint8_t *data)
{
assert(ioEnable);
@@ -800,7 +800,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
writeConfig(daddr & 0xff, req->size, data);
- return No_Fault;
+ return NoFault;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
@@ -1203,7 +1203,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
panic("Invalid Request Size");
}
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index ade7e32e6..181837c8d 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -170,9 +170,6 @@ class NSGigE : public PciDev
static const Addr size = sizeof(dp_regs);
protected:
- typedef std::deque<PacketPtr> pktbuf_t;
- typedef pktbuf_t::iterator pktiter_t;
-
/** device register file */
dp_regs regs;
dp_rom rom;
@@ -408,8 +405,8 @@ class NSGigE : public PciDev
virtual void writeConfig(int offset, int size, const uint8_t *data);
virtual void readConfig(int offset, int size, uint8_t *data);
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
bool cpuIntrPending() const;
void cpuIntrAck() { cpuIntrClear(); }
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 396e130af..1175172c4 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -95,7 +95,7 @@ PciConfigAll::startup()
}
-Fault
+Fault *
PciConfigAll::read(MemReqPtr &req, uint8_t *data)
{
@@ -112,16 +112,16 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
switch (req->size) {
// case sizeof(uint64_t):
// *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF;
- // return No_Fault;
+ // return NoFault;
case sizeof(uint32_t):
*(uint32_t*)data = 0xFFFFFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint16_t):
*(uint16_t*)data = 0xFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint8_t):
*(uint8_t*)data = 0xFF;
- return No_Fault;
+ return NoFault;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
@@ -131,7 +131,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
case sizeof(uint16_t):
case sizeof(uint8_t):
devices[device][func]->readConfig(reg, req->size, data);
- return No_Fault;
+ return NoFault;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
@@ -140,10 +140,10 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n",
daddr, req->size);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
{
Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
@@ -164,7 +164,7 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
devices[device][func]->writeConfig(reg, req->size, data);
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh
index c6a0241d8..6df033286 100644
--- a/dev/pciconfigall.hh
+++ b/dev/pciconfigall.hh
@@ -103,7 +103,7 @@ class PciConfigAll : public PioDevice
* @param data Return the field read.
* @return The fault condition of the access.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
* Write to PCI config spcae. If the device does not exit the simulator
@@ -114,7 +114,7 @@ class PciConfigAll : public PioDevice
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* Start up function to check if more than one person is using an interrupt line
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index 1d9ea137d..c469e716a 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -70,59 +70,59 @@ PciDev::PciDev(Params *p)
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
}
-Fault
+Fault *
PciDev::read(MemReqPtr &req, uint8_t *data)
-{ return No_Fault; }
+{ return NoFault; }
-Fault
+Fault *
PciDev::write(MemReqPtr &req, const uint8_t *data)
-{ return No_Fault; }
+{ return NoFault; }
-Fault
+Fault *
PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::readBar1(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
-Fault
+Fault *
PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index efc805b3f..c8d9685c1 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -189,37 +189,37 @@ class PciDev : public DmaDevice
*/
PciDev(Params *params);
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
public:
/**
* Implement the read/write as BAR accesses
*/
- Fault readBar(MemReqPtr &req, uint8_t *data);
- Fault writeBar(MemReqPtr &req, const uint8_t *data);
+ Fault * readBar(MemReqPtr &req, uint8_t *data);
+ Fault * writeBar(MemReqPtr &req, const uint8_t *data);
public:
/**
* Read from a specific BAR
*/
- virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data);
+ virtual Fault * readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
+ virtual Fault * readBar1(MemReqPtr &req, Addr daddr, uint8_t *data);
+ virtual Fault * readBar2(MemReqPtr &req, Addr daddr, uint8_t *data);
+ virtual Fault * readBar3(MemReqPtr &req, Addr daddr, uint8_t *data);
+ virtual Fault * readBar4(MemReqPtr &req, Addr daddr, uint8_t *data);
+ virtual Fault * readBar5(MemReqPtr &req, Addr daddr, uint8_t *data);
public:
/**
* Write to a specific BAR
*/
- virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ virtual Fault * writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ virtual Fault * writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ virtual Fault * writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ virtual Fault * writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ virtual Fault * writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ virtual Fault * writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data);
public:
/**
@@ -257,7 +257,7 @@ class PciDev : public DmaDevice
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
-inline Fault
+inline Fault *
PciDev::readBar(MemReqPtr &req, uint8_t *data)
{
if (isBAR(req->paddr, 0))
@@ -272,10 +272,10 @@ PciDev::readBar(MemReqPtr &req, uint8_t *data)
return readBar4(req, req->paddr - BARAddrs[4], data);
if (isBAR(req->paddr, 5))
return readBar5(req, req->paddr - BARAddrs[5], data);
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
-inline Fault
+inline Fault *
PciDev::writeBar(MemReqPtr &req, const uint8_t *data)
{
if (isBAR(req->paddr, 0))
@@ -290,7 +290,7 @@ PciDev::writeBar(MemReqPtr &req, const uint8_t *data)
return writeBar4(req, req->paddr - BARAddrs[4], data);
if (isBAR(req->paddr, 5))
return writeBar5(req, req->paddr - BARAddrs[5], data);
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
#endif // __DEV_PCIDEV_HH__
diff --git a/dev/platform.hh b/dev/platform.hh
index ee9c72617..1ee645454 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -35,7 +35,7 @@
#define __DEV_PLATFORM_HH__
#include "sim/sim_object.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
class PciConfigAll;
class IntrControl;
diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh
index 006155168..6560e15c2 100644
--- a/dev/simple_disk.hh
+++ b/dev/simple_disk.hh
@@ -34,7 +34,7 @@
#define __DEV_SIMPLE_DISK_HH__
#include "sim/sim_object.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
class DiskImage;
class PhysicalMemory;
diff --git a/dev/sinic.cc b/dev/sinic.cc
index 69239df32..e79f80678 100644
--- a/dev/sinic.cc
+++ b/dev/sinic.cc
@@ -361,23 +361,23 @@ Device::prepareWrite(int cpu, int index)
/**
* I/O read of device register
*/
-Fault
+Fault *
Device::read(MemReqPtr &req, uint8_t *data)
{
assert(config.command & PCI_CMD_MSE);
- Fault fault = readBar(req, data);
+ Fault * fault = readBar(req, data);
- if (fault == Machine_Check_Fault) {
+ if (fault == MachineCheckFault) {
panic("address does not map to a BAR pa=%#x va=%#x size=%d",
req->paddr, req->vaddr, req->size);
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
return fault;
}
-Fault
+Fault *
Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
{
int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
@@ -421,13 +421,13 @@ Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
if (raddr == Regs::IntrStatus)
devIntrClear();
- return No_Fault;
+ return NoFault;
}
/**
* IPR read of device register
*/
-Fault
+Fault *
Device::iprRead(Addr daddr, int cpu, uint64_t &result)
{
if (!regValid(daddr))
@@ -451,29 +451,29 @@ Device::iprRead(Addr daddr, int cpu, uint64_t &result)
DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",
info.name, cpu, result);
- return No_Fault;
+ return NoFault;
}
/**
* I/O write of device register
*/
-Fault
+Fault *
Device::write(MemReqPtr &req, const uint8_t *data)
{
assert(config.command & PCI_CMD_MSE);
- Fault fault = writeBar(req, data);
+ Fault * fault = writeBar(req, data);
- if (fault == Machine_Check_Fault) {
+ if (fault == MachineCheckFault) {
panic("address does not map to a BAR pa=%#x va=%#x size=%d",
req->paddr, req->vaddr, req->size);
- return Machine_Check_Fault;
+ return MachineCheckFault;
}
return fault;
}
-Fault
+Fault *
Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
{
int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
@@ -508,7 +508,7 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
if (!pioDelayWrite || !info.delay_write)
regWrite(daddr, cpu, data);
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/sinic.hh b/dev/sinic.hh
index af2f109a4..7935a7cdc 100644
--- a/dev/sinic.hh
+++ b/dev/sinic.hh
@@ -271,15 +271,15 @@ class Device : public Base
* Memory Interface
*/
public:
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
void prepareIO(int cpu, int index);
void prepareRead(int cpu, int index);
void prepareWrite(int cpu, int index);
- Fault iprRead(Addr daddr, int cpu, uint64_t &result);
- Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
- Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
+ Fault * iprRead(Addr daddr, int cpu, uint64_t &result);
+ Fault * readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
+ Fault * writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
void regWrite(Addr daddr, int cpu, const uint8_t *data);
Tick cacheAccess(MemReqPtr &req);
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index 2287a2a3d..4cda9ec36 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -76,7 +76,7 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
tsunami->cchip = this;
}
-Fault
+Fault *
TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
{
DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size);
@@ -92,81 +92,81 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
if (daddr & TSDEV_CC_BDIMS)
{
*(uint64_t*)data = dim[(daddr >> 4) & 0x3F];
- return No_Fault;
+ return NoFault;
}
if (daddr & TSDEV_CC_BDIRS)
{
*(uint64_t*)data = dir[(daddr >> 4) & 0x3F];
- return No_Fault;
+ return NoFault;
}
switch(regnum) {
case TSDEV_CC_CSR:
*(uint64_t*)data = 0x0;
- return No_Fault;
+ return NoFault;
case TSDEV_CC_MTR:
panic("TSDEV_CC_MTR not implemeted\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_MISC:
*(uint64_t*)data = (ipint << 8) & 0xF |
(itint << 4) & 0xF |
(xc->cpu_id & 0x3);
- return No_Fault;
+ return NoFault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
case TSDEV_CC_AAR2:
case TSDEV_CC_AAR3:
*(uint64_t*)data = 0;
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIM0:
*(uint64_t*)data = dim[0];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIM1:
*(uint64_t*)data = dim[1];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIM2:
*(uint64_t*)data = dim[2];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIM3:
*(uint64_t*)data = dim[3];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIR0:
*(uint64_t*)data = dir[0];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIR1:
*(uint64_t*)data = dir[1];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIR2:
*(uint64_t*)data = dir[2];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIR3:
*(uint64_t*)data = dir[3];
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DRIR:
*(uint64_t*)data = drir;
- return No_Fault;
+ return NoFault;
case TSDEV_CC_PRBEN:
panic("TSDEV_CC_PRBEN not implemented\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_IIC0:
case TSDEV_CC_IIC1:
case TSDEV_CC_IIC2:
case TSDEV_CC_IIC3:
panic("TSDEV_CC_IICx not implemented\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_MPR0:
case TSDEV_CC_MPR1:
case TSDEV_CC_MPR2:
case TSDEV_CC_MPR3:
panic("TSDEV_CC_MPRx not implemented\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_IPIR:
*(uint64_t*)data = ipint;
- return No_Fault;
+ return NoFault;
case TSDEV_CC_ITIR:
*(uint64_t*)data = itint;
- return No_Fault;
+ return NoFault;
default:
panic("default in cchip read reached, accessing 0x%x\n");
} // uint64_t
@@ -179,7 +179,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
*(uint32_t*)data = drir;
} else
panic("invalid access size(?) for tsunami register!\n");
- return No_Fault;
+ return NoFault;
case sizeof(uint16_t):
case sizeof(uint8_t):
default:
@@ -187,10 +187,10 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
}
DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
{
DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
@@ -243,16 +243,16 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
}
}
- return No_Fault;
+ return NoFault;
}
switch(regnum) {
case TSDEV_CC_CSR:
panic("TSDEV_CC_CSR write\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_MTR:
panic("TSDEV_CC_MTR write not implemented\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_MISC:
uint64_t ipreq;
ipreq = (*(uint64_t*)data >> 12) & 0xF;
@@ -285,13 +285,13 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
if(!supportedWrite)
panic("TSDEV_CC_MISC write not implemented\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
case TSDEV_CC_AAR2:
case TSDEV_CC_AAR3:
panic("TSDEV_CC_AARx write not implemeted\n");
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIM0:
case TSDEV_CC_DIM1:
case TSDEV_CC_DIM2:
@@ -341,7 +341,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
}
}
- return No_Fault;
+ return NoFault;
case TSDEV_CC_DIR0:
case TSDEV_CC_DIR1:
case TSDEV_CC_DIR2:
@@ -363,13 +363,13 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
panic("TSDEV_CC_MPRx write not implemented\n");
case TSDEV_CC_IPIR:
clearIPI(*(uint64_t*)data);
- return No_Fault;
+ return NoFault;
case TSDEV_CC_ITIR:
clearITI(*(uint64_t*)data);
- return No_Fault;
+ return NoFault;
case TSDEV_CC_IPIQ:
reqIPI(*(uint64_t*)data);
- return No_Fault;
+ return NoFault;
default:
panic("default in cchip read reached, accessing 0x%x\n");
}
@@ -384,7 +384,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
index d88ad375f..dadbdb0e3 100644
--- a/dev/tsunami_cchip.hh
+++ b/dev/tsunami_cchip.hh
@@ -105,7 +105,7 @@ class TsunamiCChip : public PioDevice
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
@@ -114,7 +114,7 @@ class TsunamiCChip : public PioDevice
* @param data The data to write.
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* post an RTC interrupt to the CPU
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 724a5bfb9..0d0d27570 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -444,7 +444,7 @@ TsunamiIO::frequency() const
return Clock::Frequency / clockInterval;
}
-Fault
+Fault *
TsunamiIO::read(MemReqPtr &req, uint8_t *data)
{
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
@@ -459,38 +459,38 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
// PIC1 mask read
case TSDEV_PIC1_MASK:
*(uint8_t*)data = ~mask1;
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_MASK:
*(uint8_t*)data = ~mask2;
- return No_Fault;
+ return NoFault;
case TSDEV_PIC1_ISR:
// !!! If this is modified 64bit case needs to be too
// Pal code has to do a 64 bit physical read because there is
// no load physical byte instruction
*(uint8_t*)data = picr;
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_ISR:
// PIC2 not implemnted... just return 0
*(uint8_t*)data = 0x00;
- return No_Fault;
+ return NoFault;
case TSDEV_TMR0_DATA:
pitimer.counter0.read(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR1_DATA:
pitimer.counter1.read(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR2_DATA:
pitimer.counter2.read(data);
- return No_Fault;
+ return NoFault;
case TSDEV_RTC_DATA:
rtc.readData(data);
- return No_Fault;
+ return NoFault;
case TSDEV_CTRL_PORTB:
if (pitimer.counter2.outputHigh())
*data = PORTB_SPKR_HIGH;
else
*data = 0x00;
- return No_Fault;
+ return NoFault;
default:
panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
}
@@ -506,7 +506,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
// Pal code has to do a 64 bit physical read because there is
// no load physical byte instruction
*(uint64_t*)data = (uint64_t)picr;
- return No_Fault;
+ return NoFault;
default:
panic("I/O Read - invalid size - va %#x size %d\n",
req->vaddr, req->size);
@@ -518,10 +518,10 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
}
panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
{
@@ -550,63 +550,63 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
tsunami->cchip->clearDRIR(55);
DPRINTF(Tsunami, "clearing pic interrupt\n");
}
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_MASK:
mask2 = *(uint8_t*)data;
//PIC2 Not implemented to interrupt
- return No_Fault;
+ return NoFault;
case TSDEV_PIC1_ACK:
// clear the interrupt on the PIC
picr &= ~(1 << (*(uint8_t*)data & 0xF));
if (!(picr & mask1))
tsunami->cchip->clearDRIR(55);
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_CMND:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_CMND:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_MMASK:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_MMASK:
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_ACK:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_RESET:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_RESET:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_MODE:
mode1 = *(uint8_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_MODE:
mode2 = *(uint8_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_MASK:
case TSDEV_DMA2_MASK:
- return No_Fault;
+ return NoFault;
case TSDEV_TMR0_DATA:
pitimer.counter0.write(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR1_DATA:
pitimer.counter1.write(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR2_DATA:
pitimer.counter2.write(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR_CTRL:
pitimer.writeControl(data);
- return No_Fault;
+ return NoFault;
case TSDEV_RTC_ADDR:
rtc.writeAddr(data);
- return No_Fault;
+ return NoFault;
case TSDEV_KBD:
- return No_Fault;
+ return NoFault;
case TSDEV_RTC_DATA:
rtc.writeData(data);
- return No_Fault;
+ return NoFault;
case TSDEV_CTRL_PORTB:
// System Control Port B not implemented
- return No_Fault;
+ return NoFault;
default:
panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data);
}
@@ -619,7 +619,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
}
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index b024ecd14..3b26ebfaa 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -330,7 +330,7 @@ class TsunamiIO : public PioDevice
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
* Process a write to one of the devices we emulate.
@@ -338,7 +338,7 @@ class TsunamiIO : public PioDevice
* @param data The data to write.
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* Post an PIC interrupt to the CPU via the CChip
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index e61137170..a4c04a79f 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -76,7 +76,7 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
tsunami->pchip = this;
}
-Fault
+Fault *
TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
{
DPRINTF(Tsunami, "read va=%#x size=%d\n",
@@ -90,60 +90,60 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
switch(daddr) {
case TSDEV_PC_WSBA0:
*(uint64_t*)data = wsba[0];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA1:
*(uint64_t*)data = wsba[1];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA2:
*(uint64_t*)data = wsba[2];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA3:
*(uint64_t*)data = wsba[3];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM0:
*(uint64_t*)data = wsm[0];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM1:
*(uint64_t*)data = wsm[1];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM2:
*(uint64_t*)data = wsm[2];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM3:
*(uint64_t*)data = wsm[3];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA0:
*(uint64_t*)data = tba[0];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA1:
*(uint64_t*)data = tba[1];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA2:
*(uint64_t*)data = tba[2];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA3:
*(uint64_t*)data = tba[3];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PCTL:
*(uint64_t*)data = pctl;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PLAT:
panic("PC_PLAT not implemented\n");
case TSDEV_PC_RES:
panic("PC_RES not implemented\n");
case TSDEV_PC_PERROR:
*(uint64_t*)data = 0x00;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PERRMASK:
*(uint64_t*)data = 0x00;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PERRSET:
panic("PC_PERRSET not implemented\n");
case TSDEV_PC_TLBIV:
panic("PC_TLBIV not implemented\n");
case TSDEV_PC_TLBIA:
*(uint64_t*)data = 0x00; // shouldn't be readable, but linux
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PMONCTL:
panic("PC_PMONCTL not implemented\n");
case TSDEV_PC_PMONCNT:
@@ -162,10 +162,10 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
}
DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
{
DPRINTF(Tsunami, "write - va=%#x size=%d \n",
@@ -179,49 +179,49 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
switch(daddr) {
case TSDEV_PC_WSBA0:
wsba[0] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA1:
wsba[1] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA2:
wsba[2] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA3:
wsba[3] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM0:
wsm[0] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM1:
wsm[1] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM2:
wsm[2] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM3:
wsm[3] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA0:
tba[0] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA1:
tba[1] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA2:
tba[2] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA3:
tba[3] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PCTL:
pctl = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PLAT:
panic("PC_PLAT not implemented\n");
case TSDEV_PC_RES:
panic("PC_RES not implemented\n");
case TSDEV_PC_PERROR:
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PERRMASK:
panic("PC_PERRMASK not implemented\n");
case TSDEV_PC_PERRSET:
@@ -229,7 +229,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_PC_TLBIV:
panic("PC_TLBIV not implemented\n");
case TSDEV_PC_TLBIA:
- return No_Fault; // value ignored, supposted to invalidate SG TLB
+ return NoFault; // value ignored, supposted to invalidate SG TLB
case TSDEV_PC_PMONCTL:
panic("PC_PMONCTL not implemented\n");
case TSDEV_PC_PMONCNT:
@@ -249,7 +249,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
#define DMA_ADDR_MASK ULL(0x3ffffffff)
diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh
index c1d95431b..ff888bea1 100644
--- a/dev/tsunami_pchip.hh
+++ b/dev/tsunami_pchip.hh
@@ -99,7 +99,7 @@ class TsunamiPChip : public PioDevice
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
/**
* Process a write to the PChip.
@@ -107,7 +107,7 @@ class TsunamiPChip : public PioDevice
* @param data The data to write.
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
* Serialize this object to the given output stream.
diff --git a/dev/uart.hh b/dev/uart.hh
index 145b9ca9e..96c22025c 100644
--- a/dev/uart.hh
+++ b/dev/uart.hh
@@ -57,8 +57,8 @@ class Uart : public PioDevice
Addr a, Addr s, HierParams *hier, Bus *bus, Tick pio_latency,
Platform *p);
- virtual Fault read(MemReqPtr &req, uint8_t *data) = 0;
- virtual Fault write(MemReqPtr &req, const uint8_t *data) = 0;
+ virtual Fault * read(MemReqPtr &req, uint8_t *data) = 0;
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data) = 0;
/**
diff --git a/dev/uart8250.cc b/dev/uart8250.cc
index 71f429069..a2e782189 100644
--- a/dev/uart8250.cc
+++ b/dev/uart8250.cc
@@ -111,7 +111,7 @@ Uart8250::Uart8250(const string &name, SimConsole *c, MemoryController *mmu,
}
-Fault
+Fault *
Uart8250::read(MemReqPtr &req, uint8_t *data)
{
Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
@@ -183,11 +183,11 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
break;
}
- return No_Fault;
+ return NoFault;
}
-Fault
+Fault *
Uart8250::write(MemReqPtr &req, const uint8_t *data)
{
Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
@@ -255,7 +255,7 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data)
panic("Tried to access a UART port that doesn't exist\n");
break;
}
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/uart8250.hh b/dev/uart8250.hh
index 88abf8e24..a0e2d344a 100644
--- a/dev/uart8250.hh
+++ b/dev/uart8250.hh
@@ -82,8 +82,8 @@ class Uart8250 : public Uart
Addr a, Addr s, HierParams *hier, Bus *pio_bus, Tick pio_latency,
Platform *p);
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Fault * read(MemReqPtr &req, uint8_t *data);
+ virtual Fault * write(MemReqPtr &req, const uint8_t *data);
/**
diff --git a/kern/freebsd/freebsd_system.cc b/kern/freebsd/freebsd_system.cc
index 283713d40..dbf60a3fc 100644
--- a/kern/freebsd/freebsd_system.cc
+++ b/kern/freebsd/freebsd_system.cc
@@ -39,6 +39,8 @@
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
+#include "arch/isa_traits.hh"
+#include "sim/byteswap.hh"
#include "targetarch/vtophys.hh"
#define TIMER_FREQUENCY 1193180
diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc
index 3a7d12443..50bbaee00 100644
--- a/kern/kernel_stats.cc
+++ b/kern/kernel_stats.cc
@@ -137,14 +137,14 @@ Statistics::regStats(const string &_name)
}
_faults
- .init(Num_Faults)
+ .init(NumFaults)
.name(name() + ".faults")
.desc("number of faults")
.flags(total | pdf | nozero | nonan)
;
- for (int i = 1; i < Num_Faults; ++i) {
- const char *str = FaultName(i);
+ for (int i = 1; i < NumFaults; ++i) {
+ const char *str = (*ListOfFaults[i])->name;
if (str)
_faults.subname(i, str);
}
diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh
index 62dd84a28..a36c73fb4 100644
--- a/kern/kernel_stats.hh
+++ b/kern/kernel_stats.hh
@@ -41,7 +41,7 @@ class ExecContext;
class FnEvent;
// What does kernel stats expect is included?
class System;
-enum Fault;
+class Fault;
namespace Kernel {
@@ -176,7 +176,13 @@ class Statistics : public Serializable
void ivlb() { _ivlb++; }
void ivle() { _ivle++; }
void hwrei() { _hwrei++; }
- void fault(Fault fault) { _faults[fault]++; }
+ void fault(Fault * fault)
+ {
+ if(fault == NoFault) _faults[0]++;
+ else if(fault == MachineCheckFault) _faults[2]++;
+ else if(fault == AlignmentFault) _faults[7]++;
+ else _faults[fault->id]++;
+ }// FIXME: When there are no generic system fault objects, this will go back to _faults[fault]++; }
void swpipl(int ipl);
void mode(cpu_mode newmode);
void context(Addr oldpcbb, Addr newpcbb);
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc
index 1144b9bdd..26a4c0d3e 100644
--- a/kern/linux/linux_system.cc
+++ b/kern/linux/linux_system.cc
@@ -44,6 +44,7 @@
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
+#include "sim/byteswap.hh"
#include "dev/platform.hh"
#include "targetarch/arguments.hh"
#include "targetarch/vtophys.hh"
@@ -100,7 +101,7 @@ LinuxSystem::LinuxSystem(Params *p)
char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
if (dp264_mv) {
- *(uint32_t*)(dp264_mv+0x18) = htog((uint32_t)127);
+ *(uint32_t*)(dp264_mv+0x18) = LittleEndianGuest::htog((uint32_t)127);
} else
panic("could not translate dp264_mv addr\n");
diff --git a/kern/linux/linux_threadinfo.hh b/kern/linux/linux_threadinfo.hh
index 0c60b9f5c..9bab1dc49 100644
--- a/kern/linux/linux_threadinfo.hh
+++ b/kern/linux/linux_threadinfo.hh
@@ -31,7 +31,7 @@
#include "kern/linux/thread_info.hh"
#include "kern/linux/sched.hh"
-#include "targetarch/vptr.hh"
+#include "sim/vptr.hh"
namespace Linux {
diff --git a/kern/tru64/dump_mbuf.cc b/kern/tru64/dump_mbuf.cc
index 215930923..85cb4de96 100644
--- a/kern/tru64/dump_mbuf.cc
+++ b/kern/tru64/dump_mbuf.cc
@@ -35,7 +35,7 @@
#include "kern/tru64/mbuf.hh"
#include "sim/host.hh"
#include "targetarch/arguments.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "targetarch/vtophys.hh"
namespace tru64 {
diff --git a/kern/tru64/mbuf.hh b/kern/tru64/mbuf.hh
index f89074653..93424858f 100644
--- a/kern/tru64/mbuf.hh
+++ b/kern/tru64/mbuf.hh
@@ -30,7 +30,7 @@
#define __MBUF_HH__
#include "sim/host.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
namespace tru64 {
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index 2079922b7..d769aab0f 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -34,7 +34,7 @@
#include "kern/tru64/printf.hh"
#include "mem/functional/memory_control.hh"
#include "targetarch/arguments.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
//void SkipFuncEvent::process(ExecContext *xc);
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index f65293474..ebcdc1553 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -36,7 +36,7 @@
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "targetarch/vtophys.hh"
using namespace std;
diff --git a/kern/tru64/tru64_system.hh b/kern/tru64/tru64_system.hh
index a9077e112..d4eb5a59a 100644
--- a/kern/tru64/tru64_system.hh
+++ b/kern/tru64/tru64_system.hh
@@ -30,7 +30,7 @@
#define __KERN_TRU64_TRU64_SYSTEM_HH__
#include "sim/system.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
class ExecContext;
diff --git a/sim/byteswap.hh b/sim/byteswap.hh
new file mode 100644
index 000000000..c5d8801ab
--- /dev/null
+++ b/sim/byteswap.hh
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2004 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.
+ */
+
+//The purpose of this file is to provide endainness conversion utility
+//functions. Depending on the endianness of the guest system, either
+//the LittleEndianGuest or BigEndianGuest namespace is used.
+
+#ifndef __SIM_BYTE_SWAP_HH__
+#define __SIM_BYTE_SWAP_HH__
+
+#include "sim/host.hh"
+
+// This lets us figure out what the byte order of the host system is
+#if defined(linux)
+#include <endian.h>
+#else
+#include <machine/endian.h>
+#endif
+
+//These functions actually perform the swapping for parameters
+//of various bit lengths
+static inline uint64_t
+swap_byte64(uint64_t x)
+{
+ return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
+ ((uint64_t)(x) & 0xff00ULL) << 40 |
+ ((uint64_t)(x) & 0xff0000ULL) << 24 |
+ ((uint64_t)(x) & 0xff000000ULL) << 8 |
+ ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
+ ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
+ ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
+ ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
+}
+
+static inline uint32_t
+swap_byte32(uint32_t x)
+{
+ return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
+ ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
+ ((uint32_t)(x) & 0xff000000) >> 24);
+
+}
+
+static inline uint16_t
+swap_byte16(uint16_t x)
+{
+ return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
+ ((uint16_t)(x) & 0xff00) >> 8);
+}
+
+//This lets the compiler figure out how to call the swap_byte functions above
+//for different data types.
+static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);}
+static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);}
+static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);}
+static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);}
+#if defined(__APPLE__)
+static inline long swap_byte(long x) {return swap_byte32((long)x);}
+static inline unsigned long swap_byte(unsigned long x)
+ { return swap_byte32((unsigned long)x);}
+#endif
+static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);}
+static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);}
+static inline uint8_t swap_byte(uint8_t x) {return x;}
+static inline int8_t swap_byte(int8_t x) {return x;}
+static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);}
+static inline float swap_byte(float x) {return swap_byte32((uint32_t)x);}
+
+//The conversion functions with fixed endianness on both ends don't need to
+//be in a namespace
+template <typename T> static inline T betole(T value) {return swap_byte(value);}
+template <typename T> static inline T letobe(T value) {return swap_byte(value);}
+
+//For conversions not involving the guest system, we can define the functions
+//conditionally based on the BYTE_ORDER macro and outside of the namespaces
+#if BYTE_ORDER == BIG_ENDIAN
+template <typename T> static inline T htole(T value) {return swap_byte(value);}
+template <typename T> static inline T letoh(T value) {return swap_byte(value);}
+template <typename T> static inline T htobe(T value) {return value;}
+template <typename T> static inline T betoh(T value) {return value;}
+#elif BYTE_ORDER == LITTLE_ENDIAN
+template <typename T> static inline T htole(T value) {return value;}
+template <typename T> static inline T letoh(T value) {return value;}
+template <typename T> static inline T htobe(T value) {return swap_byte(value);}
+template <typename T> static inline T betoh(T value) {return swap_byte(value);}
+#else
+ #error Invalid Endianess
+#endif
+
+namespace BigEndianGuest
+{
+ template <typename T>
+ static inline T gtole(T value) {return betole(value);}
+ template <typename T>
+ static inline T letog(T value) {return letobe(value);}
+ template <typename T>
+ static inline T gtobe(T value) {return value;}
+ template <typename T>
+ static inline T betog(T value) {return value;}
+ template <typename T>
+ static inline T htog(T value) {return htobe(value);}
+ template <typename T>
+ static inline T gtoh(T value) {return betoh(value);}
+}
+
+namespace LittleEndianGuest
+{
+ template <typename T>
+ static inline T gtole(T value) {return value;}
+ template <typename T>
+ static inline T letog(T value) {return value;}
+ template <typename T>
+ static inline T gtobe(T value) {return letobe(value);}
+ template <typename T>
+ static inline T betog(T value) {return betole(value);}
+ template <typename T>
+ static inline T htog(T value) {return htole(value);}
+ template <typename T>
+ static inline T gtoh(T value) {return letoh(value);}
+}
+#endif // __SIM_BYTE_SWAP_HH__
diff --git a/sim/faults.cc b/sim/faults.cc
new file mode 100644
index 000000000..58a631263
--- /dev/null
+++ b/sim/faults.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sim/faults.hh"
+
+NoFaultType * const NoFault = new NoFaultType("none");
+MachineCheckFaultType * const MachineCheckFault =
+ new MachineCheckFaultType("mchk");
+AlignmentFaultType * const AlignmentFault =
+ new AlignmentFaultType("unalign");
+
diff --git a/sim/faults.hh b/sim/faults.hh
new file mode 100644
index 000000000..d9c742b90
--- /dev/null
+++ b/sim/faults.hh
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FAULTS_HH__
+#define __FAULTS_HH__
+
+class Fault
+{
+public:
+ Fault(char * newName, int newId = 0) : name(newName), id(newId) {;}
+ const char * name;
+ int id;
+};
+
+extern class NoFaultType : public Fault
+{
+public:
+ NoFaultType(char * newName) : Fault(newName) {;}
+} * const NoFault;
+
+extern class MachineCheckFaultType : public Fault
+{
+public:
+ MachineCheckFaultType(char * newName) : Fault(newName) {;}
+} * const MachineCheckFault;
+
+extern class AlignmentFaultType : public Fault
+{
+public:
+ AlignmentFaultType(char * newName) : Fault(newName) {;}
+} * const AlignmentFault;
+
+
+#endif // __FAULTS_HH__
diff --git a/sim/process.cc b/sim/process.cc
index 395e2eb0a..59d122b48 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -251,8 +251,10 @@ static void
copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
FunctionalMemory *memory)
{
+ Addr data_ptr_swap;
for (int i = 0; i < strings.size(); ++i) {
- memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
+ data_ptr_swap = htog(data_ptr);
+ memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr));
memory->writeString(data_ptr, strings[i].c_str());
array_ptr += sizeof(Addr);
data_ptr += strings[i].size() + 1;
@@ -334,6 +336,7 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
// write contents to stack
uint64_t argc = argv.size();
+ argc = htog(argc);
memory->access(Write, stack_min, &argc, sizeof(uint64_t));
copyStringArray(argv, argv_array_base, arg_data_base, memory);
diff --git a/sim/process.hh b/sim/process.hh
index 2116ef632..43fafd9d7 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -40,7 +40,7 @@
#include <vector>
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "base/statistics.hh"
diff --git a/arch/alpha/pseudo_inst.cc b/sim/pseudo_inst.cc
index e105b3cc8..11ab55f53 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/sim/pseudo_inst.cc
@@ -33,8 +33,8 @@
#include <string>
-#include "arch/alpha/pseudo_inst.hh"
-#include "arch/alpha/vtophys.hh"
+#include "sim/pseudo_inst.hh"
+#include "targetarch/vtophys.hh"
#include "cpu/base.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/exec_context.hh"
@@ -46,7 +46,7 @@
#include "sim/stats.hh"
#include "sim/system.hh"
#include "sim/debug.hh"
-#include "targetarch/vptr.hh"
+#include "sim/vptr.hh"
using namespace std;
@@ -94,21 +94,18 @@ namespace AlphaPseudo
}
void
- m5exit(ExecContext *xc)
+ m5exit(ExecContext *xc, Tick delay)
{
- Tick delay = xc->regs.intRegFile[16];
Tick when = curTick + delay * Clock::Int::ns;
SimExit(when, "m5_exit instruction encountered");
}
void
- resetstats(ExecContext *xc)
+ resetstats(ExecContext *xc, Tick delay, Tick period)
{
if (!doStatisticsInsts)
return;
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
@@ -118,13 +115,11 @@ namespace AlphaPseudo
}
void
- dumpstats(ExecContext *xc)
+ dumpstats(ExecContext *xc, Tick delay, Tick period)
{
if (!doStatisticsInsts)
return;
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
@@ -134,11 +129,10 @@ namespace AlphaPseudo
}
void
- addsymbol(ExecContext *xc)
+ addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
{
- Addr addr = xc->regs.intRegFile[16];
char symb[100];
- CopyString(xc, symb, xc->regs.intRegFile[17], 100);
+ CopyString(xc, symb, symbolAddr, 100);
std::string symbol(symb);
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
@@ -147,13 +141,11 @@ namespace AlphaPseudo
}
void
- dumpresetstats(ExecContext *xc)
+ dumpresetstats(ExecContext *xc, Tick delay, Tick period)
{
if (!doStatisticsInsts)
return;
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
@@ -163,13 +155,11 @@ namespace AlphaPseudo
}
void
- m5checkpoint(ExecContext *xc)
+ m5checkpoint(ExecContext *xc, Tick delay, Tick period)
{
if (!doCheckpointInsts)
return;
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
@@ -177,18 +167,14 @@ namespace AlphaPseudo
Checkpoint::setup(when, repeat);
}
- void
- readfile(ExecContext *xc)
+ uint64_t
+ readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
{
const string &file = xc->cpu->system->params->readfile;
if (file.empty()) {
- xc->regs.intRegFile[0] = ULL(0);
- return;
+ return ULL(0);
}
- Addr vaddr = xc->regs.intRegFile[16];
- uint64_t len = xc->regs.intRegFile[17];
- uint64_t offset = xc->regs.intRegFile[18];
uint64_t result = 0;
int fd = ::open(file.c_str(), O_RDONLY, 0);
@@ -213,7 +199,7 @@ namespace AlphaPseudo
close(fd);
CopyIn(xc, vaddr, buf, result);
delete [] buf;
- xc->regs.intRegFile[0] = result;
+ return result;
}
class Context : public ParamContext
diff --git a/arch/alpha/pseudo_inst.hh b/sim/pseudo_inst.hh
index 0e7462a56..3857f2050 100644
--- a/arch/alpha/pseudo_inst.hh
+++ b/sim/pseudo_inst.hh
@@ -28,6 +28,11 @@
class ExecContext;
+//We need the "Tick" data type from here
+#include "sim/host.hh"
+//We need the "Addr" data type from here
+#include "arch/isa_traits.hh"
+
namespace AlphaPseudo
{
/**
@@ -41,14 +46,14 @@ namespace AlphaPseudo
void quiesce(ExecContext *xc);
void ivlb(ExecContext *xc);
void ivle(ExecContext *xc);
- void m5exit(ExecContext *xc);
+ void m5exit(ExecContext *xc, Tick delay);
void m5exit_old(ExecContext *xc);
- void resetstats(ExecContext *xc);
- void dumpstats(ExecContext *xc);
- void dumpresetstats(ExecContext *xc);
- void m5checkpoint(ExecContext *xc);
- void readfile(ExecContext *xc);
+ void resetstats(ExecContext *xc, Tick delay, Tick period);
+ void dumpstats(ExecContext *xc, Tick delay, Tick period);
+ void dumpresetstats(ExecContext *xc, Tick delay, Tick period);
+ void m5checkpoint(ExecContext *xc, Tick delay, Tick period);
+ uint64_t readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset);
void debugbreak(ExecContext *xc);
void switchcpu(ExecContext *xc);
- void addsymbol(ExecContext *xc);
+ void addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr);
}
diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc
index 4b6388a41..0fac43fc5 100644
--- a/sim/syscall_emul.cc
+++ b/sim/syscall_emul.cc
@@ -191,7 +191,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return (TheISA::IntReg)-EFAULT;
int result = unlink(path.c_str());
@@ -203,12 +203,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string old_name;
- if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
string new_name;
- if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
+ if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != NoFault)
return -EFAULT;
int64_t result = rename(old_name.c_str(), new_name.c_str());
@@ -220,7 +220,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
off_t length = xc->getSyscallArg(1);
@@ -248,7 +248,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
/* XXX endianess */
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
index 185ada2c5..739cd20e5 100644
--- a/sim/syscall_emul.hh
+++ b/sim/syscall_emul.hh
@@ -29,6 +29,9 @@
#ifndef __SIM_SYSCALL_EMUL_HH__
#define __SIM_SYSCALL_EMUL_HH__
+#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
+ defined(__FreeBSD__))
+
///
/// @file syscall_emul.hh
///
@@ -44,7 +47,7 @@
#include "base/intmath.hh" // for RoundUp
#include "mem/functional/functional.hh"
-#include "targetarch/isa_traits.hh" // for Addr
+#include "arch/isa_traits.hh" // for Addr
#include "base/trace.hh"
#include "cpu/exec_context.hh"
@@ -314,7 +317,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
if (path == "/dev/sysdev0") {
@@ -361,7 +364,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
uint32_t mode = xc->getSyscallArg(1);
@@ -414,7 +417,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct stat hostBuf;
@@ -441,13 +444,18 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process,
return -EBADF;
}
- struct stat64 hostBuf;
+#if BSD_HOST
+ struct stat hostBuf;
+ int result = fstat(process->sim_fd(fd), &hostBuf);
+#else
+ struct stat64 hostBuf;
int result = fstat64(process->sim_fd(fd), &hostBuf);
+#endif
if (result < 0)
return errno;
- OS::copyOutStat64Buf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->mem, fd, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -461,7 +469,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct stat hostBuf;
@@ -483,16 +491,21 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
+#if BSD_HOST
+ struct stat hostBuf;
+ int result = lstat(path.c_str(), &hostBuf);
+#else
struct stat64 hostBuf;
int result = lstat64(path.c_str(), &hostBuf);
+#endif
if (result < 0)
return -errno;
- OS::copyOutStat64Buf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->mem, -1, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -517,7 +530,6 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
return -errno;
OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
-
return 0;
}
@@ -530,7 +542,7 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct statfs hostBuf;
@@ -588,9 +600,9 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
typename OS::tgt_iovec tiov;
xc->mem->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec),
&tiov, sizeof(typename OS::tgt_iovec));
- hiov[i].iov_len = tiov.iov_len;
+ hiov[i].iov_len = gtoh(tiov.iov_len);
hiov[i].iov_base = new char [hiov[i].iov_len];
- xc->mem->access(Read, tiov.iov_base,
+ xc->mem->access(Read, gtoh(tiov.iov_base),
hiov[i].iov_base, hiov[i].iov_len);
}
@@ -653,22 +665,24 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
template <class OS>
SyscallReturn
getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
+ ExecContext *xc)
{
unsigned resource = xc->getSyscallArg(0);
TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
switch (resource) {
- case OS::RLIMIT_STACK:
- // max stack size in bytes: make up a number (2MB for now)
- rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
- break;
-
- default:
- std::cerr << "getrlimitFunc: unimplemented resource " << resource
- << std::endl;
- abort();
- break;
+ case OS::TGT_RLIMIT_STACK:
+ // max stack size in bytes: make up a number (2MB for now)
+ rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
+ rlp->rlim_cur = htog(rlp->rlim_cur);
+ rlp->rlim_max = htog(rlp->rlim_max);
+ break;
+
+ default:
+ std::cerr << "getrlimitFunc: unimplemented resource " << resource
+ << std::endl;
+ abort();
+ break;
}
rlp.copyOut(xc->mem);
@@ -679,12 +693,14 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
template <class OS>
SyscallReturn
gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
+ ExecContext *xc)
{
TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
getElapsedTime(tp->tv_sec, tp->tv_usec);
tp->tv_sec += seconds_since_epoch;
+ tp->tv_sec = htog(tp->tv_sec);
+ tp->tv_usec = htog(tp->tv_usec);
tp.copyOut(xc->mem);
@@ -700,7 +716,7 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
@@ -709,8 +725,8 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
struct timeval hostTimeval[2];
for (int i = 0; i < 2; ++i)
{
- hostTimeval[i].tv_sec = (*tp)[i].tv_sec;
- hostTimeval[i].tv_usec = (*tp)[i].tv_usec;
+ hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
+ hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
}
int result = utimes(path.c_str(), hostTimeval);
@@ -719,7 +735,6 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
return 0;
}
-
/// Target getrusage() function.
template <class OS>
SyscallReturn
@@ -729,7 +744,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
- if (who != OS::RUSAGE_SELF) {
+ if (who != OS::TGT_RUSAGE_SELF) {
// don't really handle THREAD or CHILDREN, but just warn and
// plow ahead
warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
@@ -737,6 +752,9 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
}
getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
+ rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
+ rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
+
rup->ru_stime.tv_sec = 0;
rup->ru_stime.tv_usec = 0;
rup->ru_maxrss = 0;
diff --git a/sim/system.cc b/sim/system.cc
index 4bcc89c56..990145826 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -35,6 +35,8 @@
#include "mem/functional/physical.hh"
#include "targetarch/vtophys.hh"
#include "sim/builder.hh"
+#include "arch/isa_traits.hh"
+#include "sim/byteswap.hh"
#include "sim/system.hh"
#include "base/trace.hh"
diff --git a/arch/alpha/vptr.hh b/sim/vptr.hh
index d1bda4061..7ec43602d 100644
--- a/arch/alpha/vptr.hh
+++ b/sim/vptr.hh
@@ -29,7 +29,8 @@
#ifndef __ARCH_ALPHA_VPTR_HH__
#define __ARCH_ALPHA_VPTR_HH__
-#include "arch/alpha/vtophys.hh"
+#include "targetarch/vtophys.hh"
+#include "arch/isa_traits.hh"
class ExecContext;
@@ -69,15 +70,16 @@ class VPtr
const VPtr<T> &operator+=(int offset)
{
ptr += offset;
- assert((ptr & (AlphaISA::PageBytes - 1)) + sizeof(T)
- < AlphaISA::PageBytes);
+ assert((ptr & (TheISA::PageBytes - 1)) + sizeof(T)
+ < TheISA::PageBytes);
return *this;
}
const VPtr<T> &operator=(Addr p)
{
- assert((p & (AlphaISA::PageBytes)) + sizeof(T) < AlphaISA::PageBytes);
+ assert((p & (TheISA::PageBytes - 1)) + sizeof(T)
+ < TheISA::PageBytes);
ptr = p;
return *this;
diff --git a/util/emacs/m5-c-style.el b/util/emacs/m5-c-style.el
index b9d16a4b1..9578e3dbe 100644
--- a/util/emacs/m5-c-style.el
+++ b/util/emacs/m5-c-style.el
@@ -1,4 +1,4 @@
-; Copyright (c) 2003-2004 The Regents of The University of Michigan
+; Copyright (c) 2003-2004, 2006 The Regents of The University of Michigan
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
(c-add-style "m5"
'((c-basic-offset . 4)
+ (indent-tabs-mode . nil)
(c-offsets-alist . ((substatement-open . 0)
(inline-open . 0)
(block-open . -4)