summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2006-03-09 18:35:28 -0500
committerGabe Black <gblack@eecs.umich.edu>2006-03-09 18:35:28 -0500
commit872bbdfc33cb82bf32576db3a57d3055a04acbac (patch)
tree837dd214bd682ac7efa515b18857bec7d4d35bef
parent3adb45144aca819c9796168ecde7a263169d9d4d (diff)
parent7b283dbc090d1197593b00fd1279b92f7c2e693e (diff)
downloadgem5-872bbdfc33cb82bf32576db3a57d3055a04acbac.tar.xz
Hand merge. Stuff probably doesn't compile.
--HG-- rename : arch/alpha/isa_desc => arch/alpha/isa/main.isa rename : arch/alpha/alpha_linux_process.cc => arch/alpha/linux/process.cc rename : arch/alpha/alpha_linux_process.hh => arch/alpha/linux/process.hh rename : arch/alpha/alpha_tru64_process.cc => arch/alpha/tru64/process.cc rename : arch/alpha/alpha_tru64_process.hh => arch/alpha/tru64/process.hh rename : cpu/exec_context.cc => cpu/cpu_exec_context.cc rename : cpu/exec_context.hh => cpu/cpu_exec_context.hh extra : convert_revision : 7d1efcedd708815d985a951f6f010fbd83dc27e8
-rw-r--r--SConscript129
-rw-r--r--arch/SConscript153
-rw-r--r--arch/alpha/SConscript91
-rw-r--r--arch/alpha/alpha_tru64_process.cc1936
-rw-r--r--arch/alpha/arguments.cc10
-rw-r--r--arch/alpha/ev5.cc249
-rw-r--r--arch/alpha/ev5.hh4
-rw-r--r--arch/alpha/faults.cc122
-rw-r--r--arch/alpha/faults.hh266
-rw-r--r--arch/alpha/freebsd/system.cc (renamed from kern/freebsd/freebsd_system.cc)40
-rw-r--r--arch/alpha/freebsd/system.hh (renamed from kern/freebsd/freebsd_system.hh)6
-rw-r--r--arch/alpha/isa/branch.isa259
-rw-r--r--arch/alpha/isa/decoder.isa819
-rw-r--r--arch/alpha/isa/fp.isa301
-rw-r--r--arch/alpha/isa/int.isa128
-rw-r--r--arch/alpha/isa/main.isa448
-rw-r--r--arch/alpha/isa/mem.isa702
-rw-r--r--arch/alpha/isa/opcdec.isa72
-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.hh336
-rw-r--r--arch/alpha/linux/aligned.hh (renamed from kern/linux/aligned.hh)8
-rw-r--r--arch/alpha/linux/hwrpb.hh (renamed from kern/linux/hwrpb.hh)8
-rw-r--r--arch/alpha/linux/process.cc589
-rw-r--r--arch/alpha/linux/process.hh (renamed from arch/alpha/alpha_linux_process.hh)11
-rw-r--r--arch/alpha/linux/system.cc (renamed from kern/linux/linux_system.cc)69
-rw-r--r--arch/alpha/linux/system.hh (renamed from kern/linux/linux_system.hh)35
-rw-r--r--arch/alpha/linux/thread_info.hh (renamed from kern/linux/thread_info.hh)8
-rw-r--r--arch/alpha/linux/threadinfo.hh (renamed from kern/linux/linux_threadinfo.hh)13
-rw-r--r--arch/alpha/process.cc61
-rw-r--r--arch/alpha/process.hh48
-rw-r--r--arch/alpha/stacktrace.cc47
-rw-r--r--arch/alpha/stacktrace.hh8
-rw-r--r--arch/alpha/system.cc299
-rw-r--r--arch/alpha/system.hh109
-rw-r--r--arch/alpha/tlb.cc (renamed from arch/alpha/alpha_memory.cc)88
-rw-r--r--arch/alpha/tlb.hh (renamed from arch/alpha/alpha_memory.hh)1
-rw-r--r--arch/alpha/tru64/process.cc543
-rw-r--r--arch/alpha/tru64/process.hh (renamed from arch/alpha/alpha_tru64_process.hh)12
-rw-r--r--arch/alpha/tru64/system.cc (renamed from kern/tru64/tru64_system.cc)28
-rw-r--r--arch/alpha/tru64/system.hh (renamed from kern/tru64/tru64_system.hh)16
-rw-r--r--arch/alpha/vtophys.cc30
-rwxr-xr-xarch/isa_parser.py906
-rw-r--r--arch/isa_specific.hh62
-rw-r--r--arch/mips/SConscript83
-rw-r--r--arch/mips/faults.cc80
-rw-r--r--arch/mips/faults.hh160
-rw-r--r--arch/mips/isa/base.isa96
-rw-r--r--arch/mips/isa/bitfields.isa67
-rw-r--r--arch/mips/isa/decoder.isa930
-rw-r--r--arch/mips/isa/formats.isa35
-rw-r--r--arch/mips/isa/formats/basic.isa66
-rw-r--r--arch/mips/isa/formats/branch.isa322
-rw-r--r--arch/mips/isa/formats/fp.isa49
-rw-r--r--arch/mips/isa/formats/int.isa130
-rw-r--r--arch/mips/isa/formats/mem.isa469
-rw-r--r--arch/mips/isa/formats/noop.isa90
-rw-r--r--arch/mips/isa/formats/tlbop.isa53
-rw-r--r--arch/mips/isa/formats/trap.isa52
-rw-r--r--arch/mips/isa/formats/unimp.isa165
-rw-r--r--arch/mips/isa/formats/unknown.isa52
-rw-r--r--arch/mips/isa/formats/util.isa148
-rw-r--r--arch/mips/isa/includes.isa39
-rw-r--r--arch/mips/isa/main.isa52
-rw-r--r--arch/mips/isa/operands.isa33
-rw-r--r--arch/mips/isa_traits.cc403
-rw-r--r--arch/mips/isa_traits.hh546
-rw-r--r--arch/mips/linux_process.cc (renamed from arch/alpha/alpha_linux_process.cc)543
-rw-r--r--arch/mips/linux_process.hh58
-rw-r--r--arch/mips/process.cc56
-rw-r--r--arch/mips/process.hh45
-rw-r--r--arch/mips/stacktrace.hh119
-rw-r--r--arch/sparc/SConscript82
-rw-r--r--arch/sparc/faults.cc248
-rw-r--r--arch/sparc/faults.hh587
-rw-r--r--arch/sparc/isa/base.isa129
-rw-r--r--arch/sparc/isa/bitfields.isa50
-rw-r--r--arch/sparc/isa/decoder.isa662
-rw-r--r--arch/sparc/isa/formats.isa19
-rw-r--r--arch/sparc/isa/formats/basic.isa68
-rw-r--r--arch/sparc/isa/formats/branch.isa62
-rw-r--r--arch/sparc/isa/formats/integerop.isa112
-rw-r--r--arch/sparc/isa/formats/mem.isa73
-rw-r--r--arch/sparc/isa/formats/noop.isa50
-rw-r--r--arch/sparc/isa/formats/trap.isa51
-rw-r--r--arch/sparc/isa/includes.isa43
-rw-r--r--arch/sparc/isa/main.isa52
-rw-r--r--arch/sparc/isa/operands.isa31
-rw-r--r--arch/sparc/isa_traits.hh527
-rw-r--r--arch/sparc/linux/process.cc374
-rw-r--r--arch/sparc/linux/process.hh58
-rw-r--r--arch/sparc/process.cc56
-rw-r--r--arch/sparc/process.hh45
-rw-r--r--arch/sparc/stacktrace.hh119
-rw-r--r--base/intmath.hh16
-rw-r--r--base/loader/elf_object.cc94
-rw-r--r--base/loader/exec_aout.h3
-rw-r--r--base/loader/exec_ecoff.h3
-rw-r--r--base/loader/object_file.hh11
-rw-r--r--base/loader/symtab.hh2
-rw-r--r--base/refcnt.hh2
-rw-r--r--base/remote_gdb.cc68
-rw-r--r--base/remote_gdb.hh2
-rw-r--r--base/sched_list.hh4
-rw-r--r--base/socket.cc3
-rw-r--r--build/SConstruct24
-rw-r--r--build/default_options/ALPHA_FS (renamed from build/build_options/default/ALPHA_FS)0
-rw-r--r--build/default_options/ALPHA_FS_TL (renamed from build/build_options/default/ALPHA_FS_TL)0
-rw-r--r--build/default_options/ALPHA_SE (renamed from build/build_options/default/ALPHA_SE)0
-rw-r--r--build/default_options/MIPS_SE2
-rw-r--r--build/default_options/SPARC_SE2
-rw-r--r--cpu/SConscript129
-rw-r--r--cpu/base.cc56
-rw-r--r--cpu/base.hh13
-rw-r--r--cpu/base_dyn_inst.cc55
-rw-r--r--cpu/base_dyn_inst.hh34
-rw-r--r--cpu/cpu_exec_context.cc (renamed from cpu/exec_context.cc)179
-rw-r--r--cpu/cpu_exec_context.hh522
-rw-r--r--cpu/cpu_models.py71
-rw-r--r--cpu/exec_context.hh576
-rw-r--r--cpu/exetrace.cc1
-rw-r--r--cpu/exetrace.hh7
-rw-r--r--cpu/inst_seq.hh2
-rw-r--r--cpu/intr_control.cc9
-rw-r--r--cpu/intr_control.hh1
-rw-r--r--cpu/memtest/memtest.cc7
-rw-r--r--cpu/memtest/memtest.hh2
-rw-r--r--cpu/o3/2bit_local_pred.hh2
-rw-r--r--cpu/o3/alpha_cpu.hh88
-rw-r--r--cpu/o3/alpha_cpu_builder.cc5
-rw-r--r--cpu/o3/alpha_cpu_impl.hh126
-rw-r--r--cpu/o3/alpha_dyn_inst.hh67
-rw-r--r--cpu/o3/alpha_dyn_inst_impl.hh44
-rw-r--r--cpu/o3/alpha_impl.hh5
-rw-r--r--cpu/o3/bpred_unit.hh2
-rw-r--r--cpu/o3/bpred_unit_impl.hh2
-rw-r--r--cpu/o3/btb.cc2
-rw-r--r--cpu/o3/btb.hh2
-rw-r--r--cpu/o3/comm.hh2
-rw-r--r--cpu/o3/commit.hh1
-rw-r--r--cpu/o3/commit_impl.hh2
-rw-r--r--cpu/o3/cpu.cc56
-rw-r--r--cpu/o3/cpu.hh31
-rw-r--r--cpu/o3/decode.hh4
-rw-r--r--cpu/o3/fetch.hh5
-rw-r--r--cpu/o3/fetch_impl.hh16
-rw-r--r--cpu/o3/free_list.hh2
-rw-r--r--cpu/o3/iew.hh1
-rw-r--r--cpu/o3/iew_impl.hh2
-rw-r--r--cpu/o3/inst_queue_impl.hh3
-rw-r--r--cpu/o3/ras.hh2
-rw-r--r--cpu/o3/regfile.hh404
-rw-r--r--cpu/o3/rename.hh3
-rw-r--r--cpu/o3/rename_map.hh4
-rw-r--r--cpu/o3/rob.hh2
-rw-r--r--cpu/o3/store_set.hh2
-rw-r--r--cpu/o3/tournament_pred.hh2
-rw-r--r--cpu/ozone/cpu.hh41
-rw-r--r--cpu/ozone/cpu_impl.hh2
-rw-r--r--cpu/ozone/ea_list.cc2
-rw-r--r--cpu/ozone/ea_list.hh2
-rw-r--r--cpu/pc_event.cc7
-rw-r--r--cpu/profile.cc1
-rw-r--r--cpu/profile.hh8
-rw-r--r--cpu/simple/cpu.cc213
-rw-r--r--cpu/simple/cpu.hh91
-rw-r--r--cpu/static_inst.cc22
-rw-r--r--cpu/static_inst.hh116
-rw-r--r--cpu/trace/reader/itx_reader.hh1
-rw-r--r--dev/alpha_access.h6
-rw-r--r--dev/alpha_console.cc61
-rw-r--r--dev/alpha_console.hh9
-rw-r--r--dev/baddev.cc5
-rw-r--r--dev/baddev.hh2
-rw-r--r--dev/disk_image.cc2
-rw-r--r--dev/ide_ctrl.cc11
-rw-r--r--dev/ide_disk.cc3
-rw-r--r--dev/isa_fake.cc13
-rw-r--r--dev/isa_fake.hh2
-rw-r--r--dev/ns_gige.cc81
-rw-r--r--dev/ns_gige.hh14
-rw-r--r--dev/ns_gige_reg.h1
-rw-r--r--dev/pciconfigall.cc15
-rw-r--r--dev/pcidev.cc4
-rw-r--r--dev/pcidev.hh6
-rw-r--r--dev/pktfifo.cc34
-rw-r--r--dev/pktfifo.hh29
-rw-r--r--dev/platform.cc1
-rw-r--r--dev/platform.hh2
-rw-r--r--dev/simple_disk.hh22
-rw-r--r--dev/sinic.cc82
-rw-r--r--dev/sinic.hh14
-rw-r--r--dev/sinicreg.hh41
-rw-r--r--dev/tsunami.cc2
-rw-r--r--dev/tsunami_cchip.cc69
-rw-r--r--dev/tsunami_io.cc68
-rw-r--r--dev/tsunami_pchip.cc68
-rw-r--r--dev/uart.hh1
-rw-r--r--dev/uart8250.cc5
-rw-r--r--dev/uart8250.hh1
-rw-r--r--kern/kernel_stats.cc46
-rw-r--r--kern/kernel_stats.hh20
-rw-r--r--kern/linux/events.cc55
-rw-r--r--kern/linux/events.hh50
-rw-r--r--kern/linux/linux.hh307
-rw-r--r--kern/linux/printk.cc2
-rw-r--r--kern/system_events.cc23
-rw-r--r--kern/tru64/dump_mbuf.cc12
-rw-r--r--kern/tru64/mbuf.hh2
-rw-r--r--kern/tru64/printf.cc4
-rw-r--r--kern/tru64/tru64.hh1292
-rw-r--r--kern/tru64/tru64_events.cc18
-rw-r--r--python/m5/objects/Ethernet.py2
-rw-r--r--python/m5/objects/System.py30
-rw-r--r--sim/byteswap.hh146
-rw-r--r--sim/faults.cc46
-rw-r--r--sim/faults.hh67
-rw-r--r--sim/host.hh8
-rw-r--r--sim/process.cc69
-rw-r--r--sim/process.hh11
-rw-r--r--sim/pseudo_inst.cc (renamed from arch/alpha/pseudo_inst.cc)97
-rw-r--r--sim/pseudo_inst.hh (renamed from arch/alpha/pseudo_inst.hh)24
-rw-r--r--sim/syscall_emul.cc177
-rw-r--r--sim/syscall_emul.hh145
-rw-r--r--sim/system.cc288
-rw-r--r--sim/system.hh55
-rw-r--r--sim/vptr.hh (renamed from arch/alpha/vptr.hh)10
-rw-r--r--util/emacs/m5-c-style.el3
-rw-r--r--util/m5/Makefile62
-rw-r--r--util/m5/m5.c18
-rw-r--r--util/m5/m5op.S196
-rw-r--r--util/m5/m5op.h31
-rw-r--r--util/m5/m5op.s121
-rw-r--r--util/pbs/jobfile.py43
-rw-r--r--util/stats/barchart.py122
-rw-r--r--util/stats/categories.py6
-rw-r--r--util/stats/chart.py4
-rw-r--r--util/stats/db.py2
-rw-r--r--util/stats/output.py37
-rwxr-xr-xutil/stats/stats.py7
243 files changed, 19787 insertions, 8686 deletions
diff --git a/SConscript b/SConscript
index 1c13a9307..3a141a7d2 100644
--- a/SConscript
+++ b/SConscript
@@ -43,11 +43,8 @@ Import('env')
###################################################
# Base sources used by all configurations.
-base_sources = Split('''
- arch/alpha/decoder.cc
- arch/alpha/faults.cc
- arch/alpha/isa_traits.cc
+base_sources = Split('''
base/circlebuf.cc
base/copyright.cc
base/cprintf.cc
@@ -84,7 +81,7 @@ base_sources = Split('''
base/stats/text.cc
cpu/base.cc
- cpu/exec_context.cc
+ cpu/cpu_exec_context.cc
cpu/exetrace.cc
cpu/op_class.cc
cpu/pc_event.cc
@@ -104,6 +101,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
@@ -119,28 +117,8 @@ base_sources = Split('''
sim/trace_context.cc
''')
-fast_cpu_sources = Split('''
- arch/alpha/fast_cpu_exec.cc
- cpu/fast/cpu.cc
- ''')
-
-simple_cpu_sources = Split('''
- arch/alpha/simple_cpu_exec.cc
- cpu/simple/cpu.cc
- ''')
-
-trace_reader_sources = Split('''
- 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
- ''')
-
+# Old FullCPU sources
full_cpu_sources = Split('''
- arch/alpha/full_cpu_exec.cc
- cpu/base_dyn_inst.cc
encumbered/cpu/full/bpred.cc
encumbered/cpu/full/commit.cc
encumbered/cpu/full/cpu.cc
@@ -153,6 +131,7 @@ full_cpu_sources = Split('''
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
@@ -177,32 +156,17 @@ full_cpu_sources = Split('''
encumbered/cpu/full/iq/standard/iq_standard.cc
''')
-o3_cpu_sources = Split('''
- arch/alpha/alpha_o3_exec.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
+trace_reader_sources = Split('''
+ 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
''')
+
+
# MySql sources
mysql_sources = Split('''
base/mysql.cc
@@ -211,14 +175,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
@@ -258,17 +214,16 @@ full_system_sources = Split('''
kern/kernel_binning.cc
kern/kernel_stats.cc
kern/system_events.cc
- kern/freebsd/freebsd_system.cc
+ kern/linux/events.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
+ sim/pseudo_inst.cc
''')
# turbolaser encumbered sources
@@ -293,12 +248,11 @@ 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
encumbered/eio/exolex.cc
encumbered/eio/libexo.cc
+ kern/linux/linux.cc
+ kern/tru64/tru64.cc
sim/process.cc
sim/syscall_emul.cc
''')
@@ -311,33 +265,22 @@ memtest_sources = Split('''
cpu/memtest/memtest.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
- ''')
+# Add a flag defining what THE_ISA should be for all compilation
+env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
-for f in targetarch_files:
- env.Command('targetarch/' + f, 'arch/alpha/' + f,
- '''echo '#include "arch/alpha/%s"' > $TARGET''' % f)
+arch_sources = SConscript('arch/SConscript',
+ exports = 'env', duplicate = False)
+cpu_sources = SConscript('cpu/SConscript',
+ exports = 'env', duplicate = False)
+
+# This is outside of cpu/SConscript since the source directory isn't
+# underneath 'cpu'.
+if 'FullCPU' in env['CPU_MODELS']:
+ cpu_sources += full_cpu_sources
# Set up complete list of sources based on configuration.
-sources = base_sources + simple_cpu_sources
+sources = base_sources + arch_sources + cpu_sources
if env['FULL_SYSTEM']:
sources += full_system_sources
@@ -364,17 +307,6 @@ env.Command(Split('base/traceflags.hh base/traceflags.cc'),
'base/traceflags.py',
'python $SOURCE $TARGET.base')
-# several files are generated from arch/$TARGET_ISA/isa_desc.
-env.Command(Split('''arch/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'''),
- Split('''arch/alpha/isa_desc
- arch/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.
@@ -407,6 +339,7 @@ def make_objs(sources, env):
# the corresponding build directory to pick up generated include
# files.
env.Append(CPPPATH='.')
+env.Append(CPPPATH='./libelf')
# Debug binary
debugEnv = env.Copy(OBJSUFFIX='.do')
diff --git a/arch/SConscript b/arch/SConscript
new file mode 100644
index 000000000..0533261a2
--- /dev/null
+++ b/arch/SConscript
@@ -0,0 +1,153 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os.path
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+# Right now there are no source files immediately in this directory
+sources = []
+
+#################################################################
+#
+# ISA "switch header" generation.
+#
+# Auto-generate arch headers that include the right ISA-specific
+# header based on the setting of THE_ISA preprocessor variable.
+#
+#################################################################
+
+# List of headers to generate
+isa_switch_hdrs = Split('''
+ isa_traits.hh
+ tlb.hh
+ process.hh
+ arguments.hh
+ stacktrace.hh
+ vtophys.hh
+ faults.hh
+ ''')
+
+# Generate the header. target[0] is the full path of the output
+# header to generate. 'source' is a dummy variable, since we get the
+# list of ISAs from env['ALL_ISA_LIST'].
+def gen_switch_hdr(target, source, env):
+ fname = str(target[0])
+ basename = os.path.basename(fname)
+ f = open(fname, 'w')
+ f.write('#include "arch/isa_specific.hh"\n')
+ cond = '#if'
+ for isa in env['ALL_ISA_LIST']:
+ f.write('%s THE_ISA == %s_ISA\n#include "arch/%s/%s"\n'
+ % (cond, isa.upper(), isa, basename))
+ cond = '#elif'
+ f.write('#else\n#error "THE_ISA not set"\n#endif\n')
+ f.close()
+ return 0
+
+# String to print when generating header
+def gen_switch_hdr_string(target, source, env):
+ return "Generating ISA switch header " + str(target[0])
+
+# Build SCons Action object. 'varlist' specifies env vars that this
+# action depends on; when env['ALL_ISA_LIST'] changes these actions
+# should get re-executed.
+switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string,
+ varlist=['ALL_ISA_LIST'])
+
+# Instantiate actions for each header
+for hdr in isa_switch_hdrs:
+ env.Command(hdr, [], switch_hdr_action)
+
+#################################################################
+#
+# Include architecture-specific files.
+#
+#################################################################
+
+#
+# Build a SCons scanner for ISA files
+#
+import SCons.Scanner
+
+def ISAScan():
+ return SCons.Scanner.Classic("ISAScan",
+ "$ISASUFFIXES",
+ "SRCDIR",
+ '^[ \t]*##[ \t]*include[ \t]*"([^>"]+)"')
+
+def ISAPath(env, dir, target=None, source=None, a=None):
+ return (Dir(env['SRCDIR']), Dir('.'))
+
+iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"],
+ path_function = ISAPath)
+env.Append(SCANNERS = iscan)
+
+#
+# Now create a Builder object that uses isa_parser.py to generate C++
+# output from the ISA description (*.isa) files.
+#
+
+# Convert to File node to fix path
+isa_parser = File('isa_parser.py')
+cpu_models_file = File('#m5/cpu/cpu_models.py')
+
+# This sucks in the defintions of the CpuModel objects.
+execfile(cpu_models_file.srcnode().abspath)
+
+# Several files are generated from the ISA description.
+# We always get the basic decoder and header file.
+isa_desc_gen_files = Split('decoder.cc decoder.hh')
+# We also get an execute file for each selected CPU model.
+isa_desc_gen_files += [CpuModel.dict[cpu].filename
+ for cpu in env['CPU_MODELS']]
+
+# The emitter patches up the sources & targets to include the
+# autogenerated files as targets and isa parser itself as a source.
+def isa_desc_emitter(target, source, env):
+ return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
+
+# Pieces are in place, so create the builder.
+isa_desc_builder = Builder(action='$SOURCES $TARGET.dir $CPU_MODELS',
+ source_scanner = iscan,
+ emitter = isa_desc_emitter)
+
+env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
+
+#
+# Now include other ISA-specific sources from the ISA subdirectories.
+#
+
+isa = env['TARGET_ISA'] # someday this may be a list of ISAs
+
+# Let the target architecture define what additional sources it needs
+sources += SConscript(os.path.join(isa, 'SConscript'),
+ exports = 'env', duplicate = False)
+
+Return('sources')
diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript
new file mode 100644
index 000000000..ed7fd3404
--- /dev/null
+++ b/arch/alpha/SConscript
@@ -0,0 +1,91 @@
+# -*- 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.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ tlb.cc
+ arguments.cc
+ ev5.cc
+ osfpal.cc
+ stacktrace.cc
+ vtophys.cc
+ system.cc
+ freebsd/system.cc
+ linux/system.cc
+ tru64/system.cc
+ ''')
+
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ linux/process.cc
+ tru64/process.cc
+ process.cc
+ ''')
+
+# Set up complete list of sources based on configuration.
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc
deleted file mode 100644
index a9c7b5c74..000000000
--- a/arch/alpha/alpha_tru64_process.cc
+++ /dev/null
@@ -1,1936 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#if defined(__OpenBSD__)
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h> // for host open() flags
-#include <string.h> // for memset()
-#include <unistd.h>
-
-#include "arch/alpha/alpha_common_syscall_emul.hh"
-#include "arch/alpha/alpha_tru64_process.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "mem/translating_port.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/host.hh"
-#include "sim/process.hh"
-#include "sim/root.hh"
-#include "sim/syscall_emul.hh"
-
-using namespace std;
-
-typedef struct stat global_stat;
-typedef struct statfs global_statfs;
-typedef struct dirent global_dirent;
-
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Tru64
-/// syscall interface.
-///
-class Tru64 {
-
- public:
-
- //@{
- /// Basic Tru64 types.
- typedef uint64_t size_t;
- typedef uint64_t off_t;
- typedef uint16_t nlink_t;
- typedef int32_t dev_t;
- typedef uint32_t uid_t;
- typedef uint32_t gid_t;
- typedef uint32_t time_t;
- typedef uint32_t mode_t;
- typedef uint32_t ino_t;
- typedef struct { int val[2]; } quad;
- typedef quad fsid_t;
- //@}
-
- //@{
- /// open(2) flag values.
- static const int TGT_O_RDONLY = 00000000;
- static const int TGT_O_WRONLY = 00000001;
- static const int TGT_O_RDWR = 00000002;
- static const int TGT_O_NONBLOCK = 00000004;
- static const int TGT_O_APPEND = 00000010;
- static const int TGT_O_CREAT = 00001000;
- static const int TGT_O_TRUNC = 00002000;
- static const int TGT_O_EXCL = 00004000;
- static const int TGT_O_NOCTTY = 00010000;
- static const int TGT_O_SYNC = 00040000;
- static const int TGT_O_DRD = 00100000;
- static const int TGT_O_DIRECTIO = 00200000;
- static const int TGT_O_CACHE = 00400000;
- static const int TGT_O_DSYNC = 02000000;
- static const int TGT_O_RSYNC = 04000000;
- //@}
-
- /// This table maps the target open() flags to the corresponding
- /// host open() flags.
- static OpenFlagTransTable openFlagTable[];
-
- /// Number of entries in openFlagTable[].
- static const int NUM_OPEN_FLAGS;
-
- /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat
- /// structure, and a new set of syscall numbers for stat calls.
- /// On some hosts (notably Linux) define st_atime, st_mtime, and
- /// st_ctime as macros, so we append an X to get around this.
- struct F64_stat {
- dev_t st_dev; //!< st_dev
- int32_t st_retired1; //!< st_retired1
- mode_t st_mode; //!< st_mode
- nlink_t st_nlink; //!< st_nlink
- uint16_t st_nlink_reserved; //!< st_nlink_reserved
- uid_t st_uid; //!< st_uid
- gid_t st_gid; //!< st_gid
- dev_t st_rdev; //!< st_rdev
- dev_t st_ldev; //!< st_ldev
- off_t st_size; //!< st_size
- time_t st_retired2; //!< st_retired2
- int32_t st_uatime; //!< st_uatime
- time_t st_retired3; //!< st_retired3
- int32_t st_umtime; //!< st_umtime
- time_t st_retired4; //!< st_retired4
- int32_t st_uctime; //!< st_uctime
- int32_t st_retired5; //!< st_retired5
- int32_t st_retired6; //!< st_retired6
- uint32_t st_flags; //!< st_flags
- uint32_t st_gen; //!< st_gen
- uint64_t st_spare[4]; //!< st_spare[4]
- ino_t st_ino; //!< st_ino
- int32_t st_ino_reserved; //!< st_ino_reserved
- time_t st_atimeX; //!< st_atime
- int32_t st_atime_reserved; //!< st_atime_reserved
- time_t st_mtimeX; //!< st_mtime
- int32_t st_mtime_reserved; //!< st_mtime_reserved
- time_t st_ctimeX; //!< st_ctime
- int32_t st_ctime_reserved; //!< st_ctime_reserved
- uint64_t st_blksize; //!< st_blksize
- uint64_t st_blocks; //!< st_blocks
- };
-
-
- /// Old Tru64 v4.x stat struct.
- /// Tru64 maintains backwards compatibility with v4.x by
- /// implementing another set of stat functions using the old
- /// structure definition and binding them to the old syscall
- /// numbers.
- struct pre_F64_stat {
- dev_t st_dev;
- ino_t st_ino;
- mode_t st_mode;
- nlink_t st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- dev_t st_rdev;
- off_t st_size;
- time_t st_atimeX;
- int32_t st_uatime;
- time_t st_mtimeX;
- int32_t st_umtime;
- time_t st_ctimeX;
- int32_t st_uctime;
- uint32_t st_blksize;
- int32_t st_blocks;
- uint32_t st_flags;
- uint32_t st_gen;
- };
-
- /// For statfs().
- struct F64_statfs {
- int16_t f_type;
- int16_t f_flags;
- int32_t f_retired1;
- int32_t f_retired2;
- int32_t f_retired3;
- int32_t f_retired4;
- int32_t f_retired5;
- int32_t f_retired6;
- int32_t f_retired7;
- fsid_t f_fsid;
- int32_t f_spare[9];
- char f_retired8[90];
- char f_retired9[90];
- uint64_t dummy[10]; // was union mount_info mount_info;
- uint64_t f_flags2;
- int64_t f_spare2[14];
- int64_t f_fsize;
- int64_t f_bsize;
- int64_t f_blocks;
- int64_t f_bfree;
- int64_t f_bavail;
- int64_t f_files;
- int64_t f_ffree;
- char f_mntonname[1024];
- char f_mntfromname[1024];
- };
-
- /// For old Tru64 v4.x statfs()
- struct pre_F64_statfs {
- int16_t f_type;
- int16_t f_flags;
- int32_t f_fsize;
- int32_t f_bsize;
- int32_t f_blocks;
- int32_t f_bfree;
- int32_t f_bavail;
- int32_t f_files;
- int32_t f_ffree;
- fsid_t f_fsid;
- int32_t f_spare[9];
- char f_mntonname[90];
- char f_mntfromname[90];
- uint64_t dummy[10]; // was union mount_info mount_info;
- };
-
- /// For getdirentries().
- struct dirent
- {
- ino_t d_ino; //!< file number of entry
- uint16_t d_reclen; //!< length of this record
- uint16_t d_namlen; //!< length of string in d_name
- char d_name[256]; //!< dummy name length
- };
-
-
- /// Length of strings in struct utsname (plus 1 for null char).
- static const int _SYS_NMLN = 32;
-
- /// Interface struct for uname().
- struct utsname {
- char sysname[_SYS_NMLN]; //!< System name.
- char nodename[_SYS_NMLN]; //!< Node name.
- char release[_SYS_NMLN]; //!< OS release.
- char version[_SYS_NMLN]; //!< OS version.
- char machine[_SYS_NMLN]; //!< Machine type.
- };
-
- //@{
- /// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- // TIOCGETS not defined in tru64, so I made up a number
- static const unsigned TIOCGETS = 0x40000000;
- static const unsigned TIOCGETA = 0x402c7413;
- //@}
-
- /// Resource enumeration for getrlimit().
- enum rlimit_resources {
- 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
- };
-
- /// Limit struct for getrlimit/setrlimit.
- struct rlimit {
- uint64_t rlim_cur; //!< soft limit
- uint64_t rlim_max; //!< hard limit
- };
-
-
- /// For mmap().
- static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
-
- //@{
- /// For getsysinfo().
- static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
- static const unsigned GSI_CPU_INFO = 59; //!< CPU information
- static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
- static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
- static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
- static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
- static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
- //@}
-
- /// For getsysinfo() GSI_CPU_INFO option.
- struct cpu_info {
- uint32_t current_cpu; //!< current_cpu
- uint32_t cpus_in_box; //!< cpus_in_box
- uint32_t cpu_type; //!< cpu_type
- uint32_t ncpus; //!< ncpus
- uint64_t cpus_present; //!< cpus_present
- uint64_t cpus_running; //!< cpus_running
- uint64_t cpu_binding; //!< cpu_binding
- uint64_t cpu_ex_binding; //!< cpu_ex_binding
- uint32_t mhz; //!< mhz
- uint32_t unused[3]; //!< future expansion
- };
-
- //@{
- /// For setsysinfo().
- static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
- //@}
-
- /// For gettimeofday.
- struct timeval {
- uint32_t tv_sec; //!< seconds
- uint32_t tv_usec; //!< microseconds
- };
-
- //@{
- /// For getrusage().
- static const int RUSAGE_THREAD = 1;
- static const int RUSAGE_SELF = 0;
- static const int RUSAGE_CHILDREN = -1;
- //@}
-
- /// For getrusage().
- struct rusage {
- struct timeval ru_utime; //!< user time used
- struct timeval ru_stime; //!< system time used
- uint64_t ru_maxrss; //!< ru_maxrss
- uint64_t ru_ixrss; //!< integral shared memory size
- uint64_t ru_idrss; //!< integral unshared data "
- uint64_t ru_isrss; //!< integral unshared stack "
- uint64_t ru_minflt; //!< page reclaims - total vmfaults
- uint64_t ru_majflt; //!< page faults
- uint64_t ru_nswap; //!< swaps
- uint64_t ru_inblock; //!< block input operations
- uint64_t ru_oublock; //!< block output operations
- uint64_t ru_msgsnd; //!< messages sent
- uint64_t ru_msgrcv; //!< messages received
- uint64_t ru_nsignals; //!< signals received
- uint64_t ru_nvcsw; //!< voluntary context switches
- uint64_t ru_nivcsw; //!< involuntary "
- };
-
- /// For sigreturn().
- struct sigcontext {
- int64_t sc_onstack; //!< sigstack state to restore
- int64_t sc_mask; //!< signal mask to restore
- int64_t sc_pc; //!< pc at time of signal
- int64_t sc_ps; //!< psl to retore
- int64_t sc_regs[32]; //!< processor regs 0 to 31
- int64_t sc_ownedfp; //!< fp has been used
- int64_t sc_fpregs[32]; //!< fp regs 0 to 31
- uint64_t sc_fpcr; //!< floating point control reg
- uint64_t sc_fp_control; //!< software fpcr
- int64_t sc_reserved1; //!< reserved for kernel
- uint32_t sc_kreserved1; //!< reserved for kernel
- uint32_t sc_kreserved2; //!< reserved for kernel
- size_t sc_ssize; //!< stack size
- caddr_t sc_sbase; //!< stack start
- uint64_t sc_traparg_a0; //!< a0 argument to trap on exc
- uint64_t sc_traparg_a1; //!< a1 argument to trap on exc
- uint64_t sc_traparg_a2; //!< a2 argument to trap on exc
- uint64_t sc_fp_trap_pc; //!< imprecise pc
- uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg
- uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc
- };
-
-
- /// For table().
- static const int TBL_SYSINFO = 12;
-
- /// For table().
- struct tbl_sysinfo {
- uint64_t si_user; //!< User time
- uint64_t si_nice; //!< Nice time
- uint64_t si_sys; //!< System time
- uint64_t si_idle; //!< Idle time
- uint64_t si_hz; //!< hz
- uint64_t si_phz; //!< phz
- uint64_t si_boottime; //!< Boot time in seconds
- uint64_t wait; //!< Wait time
- uint32_t si_max_procs; //!< rpb->rpb_numprocs
- uint32_t pad; //!< padding
- };
-
-
- /// For stack_create.
- struct vm_stack {
- // was void *
- Addr address; //!< address hint
- size_t rsize; //!< red zone size
- size_t ysize; //!< yellow zone size
- size_t gsize; //!< green zone size
- size_t swap; //!< amount of swap to reserve
- size_t incr; //!< growth increment
- uint64_t align; //!< address alignment
- uint64_t flags; //!< MAP_FIXED etc.
- // was struct memalloc_attr *
- Addr attr; //!< allocation policy
- uint64_t reserved; //!< reserved
- };
-
- /// Return values for nxm calls.
- enum {
- KERN_NOT_RECEIVER = 7,
- KERN_NOT_IN_SET = 12
- };
-
- /// For nxm_task_init.
- static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP
-
- /// Task attribute structure.
- struct nxm_task_attr {
- int64_t nxm_callback; //!< nxm_callback
- unsigned int nxm_version; //!< nxm_version
- unsigned short nxm_uniq_offset; //!< nxm_uniq_offset
- unsigned short flags; //!< flags
- int nxm_quantum; //!< nxm_quantum
- int pad1; //!< pad1
- int64_t pad2; //!< pad2
- };
-
- /// Signal set.
- typedef uint64_t sigset_t;
-
- /// Thread state shared between user & kernel.
- struct ushared_state {
- sigset_t sigmask; //!< thread signal mask
- sigset_t sig; //!< thread pending mask
- // struct nxm_pth_state *
- Addr pth_id; //!< out-of-line state
- int flags; //!< shared flags
-#define US_SIGSTACK 0x1 // thread called sigaltstack
-#define US_ONSTACK 0x2 // thread is running on altstack
-#define US_PROFILE 0x4 // thread called profil
-#define US_SYSCALL 0x8 // thread in syscall
-#define US_TRAP 0x10 // thread has trapped
-#define US_YELLOW 0x20 // thread has mellowed yellow
-#define US_YZONE 0x40 // thread has zoned out
-#define US_FP_OWNED 0x80 // thread used floating point
-
- int cancel_state; //!< thread's cancelation state
-#define US_CANCEL 0x1 // cancel pending
-#define US_NOCANCEL 0X2 // synch cancel disabled
-#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled
-#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled
-#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
-#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
- US_ASYNC_NOCANCEL)
-
- // These are semi-shared. They are always visible to
- // the kernel but are never context-switched by the library.
-
- int nxm_ssig; //!< scheduler's synchronous signals
- int reserved1; //!< reserved1
- int64_t nxm_active; //!< scheduler active
- int64_t reserved2; //!< reserved2
- };
-
- struct nxm_sched_state {
- struct ushared_state nxm_u; //!< state own by user thread
- unsigned int nxm_bits; //!< scheduler state / slot
- int nxm_quantum; //!< quantum count-down value
- int nxm_set_quantum; //!< quantum reset value
- int nxm_sysevent; //!< syscall state
- // struct nxm_upcall *
- Addr nxm_uc_ret; //!< stack ptr of null thread
- // void *
- Addr nxm_tid; //!< scheduler's thread id
- int64_t nxm_va; //!< page fault address
- // struct nxm_pth_state *
- Addr nxm_pthid; //!< id of null thread
- uint64_t nxm_bound_pcs_count; //!< bound PCS thread count
- int64_t pad[2]; //!< pad
- };
-
- /// nxm_shared.
- struct nxm_shared {
- int64_t nxm_callback; //!< address of upcall routine
- unsigned int nxm_version; //!< version number
- unsigned short nxm_uniq_offset; //!< correction factor for TEB
- unsigned short pad1; //!< pad1
- int64_t space[2]; //!< future growth
- struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
- };
-
- /// nxm_slot_state_t.
- enum nxm_slot_state_t {
- NXM_SLOT_AVAIL,
- NXM_SLOT_BOUND,
- NXM_SLOT_UNBOUND,
- NXM_SLOT_EMPTY
- };
-
- /// nxm_config_info
- struct nxm_config_info {
- int nxm_nslots_per_rad; //!< max number of VP slots per RAD
- int nxm_nrads; //!< max number of RADs
- // nxm_slot_state_t *
- Addr nxm_slot_state; //!< per-VP slot state
- // struct nxm_shared *
- Addr nxm_rad[1]; //!< per-RAD shared areas
- };
-
- /// For nxm_thread_create.
- enum nxm_thread_type {
- NXM_TYPE_SCS = 0,
- NXM_TYPE_VP = 1,
- NXM_TYPE_MANAGER = 2
- };
-
- /// Thread attributes.
- struct nxm_thread_attr {
- int version; //!< version
- int type; //!< type
- int cancel_flags; //!< cancel_flags
- int priority; //!< priority
- int policy; //!< policy
- int signal_type; //!< signal_type
- // void *
- Addr pthid; //!< pthid
- sigset_t sigmask; //!< sigmask
- /// Initial register values.
- struct {
- uint64_t pc; //!< pc
- uint64_t sp; //!< sp
- uint64_t a0; //!< a0
- } registers;
- uint64_t pad2[2]; //!< pad2
- };
-
- /// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
- template <class T>
- static void
- copyOutStatBuf(TranslatingPort *memPort, Addr addr, global_stat *host)
- {
- 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.copyOut(memPort);
- }
-
- /// Helper function to convert a host statfs buffer to a target statfs
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by statfs() and fstatfs().
- template <class T>
- static void
- copyOutStatfsBuf(TranslatingPort *memPort, Addr addr, global_statfs *host)
- {
- TypedBufferArg<T> tgt(addr);
-
-#if defined(__OpenBSD__)
- tgt->f_type = 0;
-#else
- tgt->f_type = 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;
- memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
-
- tgt.copyOut(memPort);
- }
-
- class F64 {
- public:
- static void copyOutStatBuf(TranslatingPort *memPort, Addr addr,
- global_stat *host)
- {
- Tru64::copyOutStatBuf<Tru64::F64_stat>(memPort, addr, host);
- }
-
- static void copyOutStatfsBuf(TranslatingPort *memPort, Addr addr,
- global_statfs *host)
- {
- Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(memPort, addr, host);
- }
- };
-
- class PreF64 {
- public:
- static void copyOutStatBuf(TranslatingPort *memPort, Addr addr,
- global_stat *host)
- {
- Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(memPort, addr, host);
- }
-
- static void copyOutStatfsBuf(TranslatingPort *memPort, Addr addr,
- global_statfs *host)
- {
- Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(memPort, addr, host);
- }
- };
-
- /// Helper function to convert a host stat buffer to an old pre-F64
- /// (4.x) target stat buffer. Also copies the target buffer out to
- /// the simulated memory space. Used by pre_F64_stat(),
- /// pre_F64_fstat(), and pre_F64_lstat().
- static void
- copyOutPreF64StatBuf(TranslatingPort *memPort, Addr addr, struct stat *host)
- {
- 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.copyOut(memPort);
- }
-
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Target uname() handler.
- static SyscallReturn
- unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "OSF1");
- strcpy(name->nodename, hostname);
- strcpy(name->release, "V5.1");
- strcpy(name->version, "732");
- strcpy(name->machine, "alpha");
-
- name.copyOut(xc->port);
- return 0;
- }
-
-
- /// Target getsysyinfo() handler.
- static SyscallReturn
- getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
- unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case Tru64::GSI_MAX_CPU: {
- TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
- *max_cpu = process->numCpus();
- max_cpu.copyOut(xc->port);
- 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.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_PHYSMEM: {
- TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
- *physmem = 1024 * 1024; // physical memory in KB
- physmem.copyOut(xc->port);
- return 1;
- }
-
- 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.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_PROC_TYPE: {
- TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
- *proc_type = 11;
- proc_type.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_PLATFORM_NAME: {
- BufferArg bufArg(xc->getSyscallArg(1), nbytes);
- strncpy((char *)bufArg.bufferPtr(),
- "COMPAQ Professional Workstation XP1000",
- nbytes);
- bufArg.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_CLK_TCK: {
- TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
- *clk_hz = 1024;
- clk_hz.copyOut(xc->port);
- return 1;
- }
-
- default:
- warn("getsysinfo: unknown op %d\n", op);
- break;
- }
-
- return 0;
- }
-
- /// Target setsysyinfo() handler.
- static SyscallReturn
- setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
-
- switch (op) {
- case SSI_IEEE_FP_CONTROL:
- warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
- xc->getSyscallArg(1));
- break;
-
- default:
- warn("setsysinfo: unknown op %d\n", op);
- break;
- }
-
- return 0;
- }
-
- /// Target fnctl() handler.
- static SyscallReturn
- fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int fd = xc->getSyscallArg(0);
-
- if (fd < 0 || process->sim_fd(fd) < 0)
- return -EBADF;
-
- int cmd = xc->getSyscallArg(1);
- switch (cmd) {
- case 0: // F_DUPFD
- // if we really wanted to support this, we'd need to do it
- // in the target fd space.
- warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
- return -EMFILE;
-
- case 1: // F_GETFD (get close-on-exec flag)
- case 2: // F_SETFD (set close-on-exec flag)
- return 0;
-
- case 3: // F_GETFL (get file flags)
- case 4: // F_SETFL (set file flags)
- // not sure if this is totally valid, but we'll pass it through
- // to the underlying OS
- warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
- return fcntl(process->sim_fd(fd), cmd);
- // return 0;
-
- case 7: // F_GETLK (get lock)
- case 8: // F_SETLK (set lock)
- case 9: // F_SETLKW (set lock and wait)
- // don't mess with file locking... just act like it's OK
- warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
- return 0;
-
- default:
- warn("Unknown fcntl command %d\n", cmd);
- return 0;
- }
- }
-
-
- /// Target getdirentries() handler.
- static SyscallReturn
- getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
-#ifdef __CYGWIN__
- panic("getdirent not implemented on cygwin!");
-#else
- int fd = process->sim_fd(xc->getSyscallArg(0));
- Addr tgt_buf = xc->getSyscallArg(1);
- int tgt_nbytes = xc->getSyscallArg(2);
- Addr tgt_basep = xc->getSyscallArg(3);
-
- char * const host_buf = new char[tgt_nbytes];
-
- // just pass basep through uninterpreted.
- TypedBufferArg<int64_t> basep(tgt_basep);
- basep.copyIn(xc->port);
- long host_basep = (off_t)*basep;
- int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
-
- // check for error
- if (host_result < 0) {
- delete [] host_buf;
- return -errno;
- }
-
- // no error: copy results back to target space
- Addr tgt_buf_ptr = tgt_buf;
- char *host_buf_ptr = host_buf;
- char *host_buf_end = host_buf + host_result;
- while (host_buf_ptr < host_buf_end) {
- global_dirent *host_dp = (global_dirent *)host_buf_ptr;
- int namelen = strlen(host_dp->d_name);
-
- // Actual size includes padded string rounded up for alignment.
- // Subtract 256 for dummy char array in Tru64::dirent definition.
- // Add 1 to namelen for terminating null char.
- int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
- TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
- tgt_dp->d_ino = host_dp->d_ino;
- tgt_dp->d_reclen = tgt_bufsize;
- tgt_dp->d_namlen = namelen;
- strcpy(tgt_dp->d_name, host_dp->d_name);
- tgt_dp.copyOut(xc->port);
-
- tgt_buf_ptr += tgt_bufsize;
- host_buf_ptr += host_dp->d_reclen;
- }
-
- delete [] host_buf;
-
- *basep = host_basep;
- basep.copyOut(xc->port);
-
- return tgt_buf_ptr - tgt_buf;
-#endif
- }
-
- /// Target sigreturn() handler.
- static SyscallReturn
- sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- RegFile *regs = &xc->regs;
- TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
-
- sc.copyIn(xc->port);
-
- // Restore state from sigcontext structure.
- // Note that we'll advance PC <- NPC before the end of the cycle,
- // so we need to restore the desired PC into NPC.
- // The current regs->pc will get clobbered.
- regs->npc = 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->miscRegs.fpcr = sc->sc_fpcr;
-
- return 0;
- }
-
- /// Target table() handler.
- static SyscallReturn
- tableFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int id = xc->getSyscallArg(0); // table ID
- int index = xc->getSyscallArg(1); // index into table
- // arg 2 is buffer pointer; type depends on table ID
- int nel = xc->getSyscallArg(3); // number of elements
- int lel = xc->getSyscallArg(4); // expected element size
-
- switch (id) {
- case Tru64::TBL_SYSINFO: {
- if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
- return -EINVAL;
- TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
-
- const int clk_hz = one_million;
- elp->si_user = 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.copyOut(xc->port);
- return 0;
- }
-
- default:
- cerr << "table(): id " << id << " unknown." << endl;
- return -EINVAL;
- }
- }
-
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- /// Number of syscalls in syscallDescs[].
- static const int Num_Syscall_Descs;
-
- /// Max supported syscall number.
- static const int Max_Syscall_Desc;
-
- //
- // Mach syscalls -- identified by negated syscall numbers
- //
-
- /// Create a stack region for a thread.
- static SyscallReturn
- stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
-
- argp.copyIn(xc->port);
-
- // 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);
- process->next_thread_stack_base -= stack_size;
- argp.copyOut(xc->port);
- }
-
- return 0;
- }
-
- /// NXM library version stamp.
- static
- const int NXM_LIB_VERSION = 301003;
-
- /// This call sets up the interface between the user and kernel
- /// schedulers by creating a shared-memory region. The shared memory
- /// region has several structs, some global, some per-RAD, some per-VP.
- static SyscallReturn
- nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
- TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
-
- attrp.copyIn(xc->port);
-
- if (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) {
- cerr << "nxm_task_init: bad flag value " << attrp->flags
- << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
- abort();
- }
-
- const Addr base_addr = 0x12000; // was 0x3f0000000LL;
- Addr cur_addr = base_addr; // next addresses to use
- // first comes the config_info struct
- Addr config_addr = cur_addr;
- cur_addr += sizeof(Tru64::nxm_config_info);
- // next comes the per-cpu state vector
- Addr slot_state_addr = cur_addr;
- int slot_state_size =
- process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
- cur_addr += slot_state_size;
- // now the per-RAD state struct (we only support one RAD)
- cur_addr = 0x14000; // bump up addr for alignment
- Addr rad_state_addr = cur_addr;
- int rad_state_size =
- (sizeof(Tru64::nxm_shared)
- + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
- cur_addr += rad_state_size;
-
- // now initialize a config_info struct and copy it out to user space
- TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
-
- config->nxm_nslots_per_rad = 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.copyOut(xc->port);
-
- // initialize the slot_state array and copy it out
- TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
- slot_state_size);
- for (int i = 0; i < process->numCpus(); ++i) {
- // CPU 0 is bound to the calling process; all others are available
- slot_state[i] =
- (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
- }
-
- slot_state.copyOut(xc->port);
-
- // same for the per-RAD "shared" struct. Note that we need to
- // allocate extra bytes for the per-VP array which is embedded at
- // the end.
- TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
- rad_state_size);
-
- rad_state->nxm_callback = attrp->nxm_callback;
- rad_state->nxm_version = attrp->nxm_version;
- rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
- for (int i = 0; i < process->numCpus(); ++i) {
- Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
- ssp->nxm_u.sigmask = 0;
- ssp->nxm_u.sig = 0;
- ssp->nxm_u.flags = 0;
- ssp->nxm_u.cancel_state = 0;
- ssp->nxm_u.nxm_ssig = 0;
- ssp->nxm_bits = 0;
- ssp->nxm_quantum = attrp->nxm_quantum;
- ssp->nxm_set_quantum = attrp->nxm_quantum;
- ssp->nxm_sysevent = 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;
- }
- else {
- ssp->nxm_u.pth_id = 0;
- ssp->nxm_u.nxm_active = 0;
- }
- }
-
- rad_state.copyOut(xc->port);
-
- //
- // copy pointer to shared config area out to user
- //
- *configptr_ptr = config_addr;
- configptr_ptr.copyOut(xc->port);
-
- // Register this as a valid address range with the process
- process->nxm_start = base_addr;
- process->nxm_end = cur_addr;
-
- return 0;
- }
-
- /// Initialize execution context.
- static void
- init_exec_context(ExecContext *ec,
- Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
- {
- memset(&ec->regs, 0, sizeof(ec->regs));
-
- ec->regs.intRegFile[ArgumentReg0] = attrp->registers.a0;
- ec->regs.intRegFile[27/*t12*/] = attrp->registers.pc;
- ec->regs.intRegFile[StackPointerReg] = attrp->registers.sp;
- ec->regs.miscRegs.uniq = uniq_val;
-
- ec->regs.pc = attrp->registers.pc;
- ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
-
- ec->activate();
- }
-
- /// Create thread.
- static SyscallReturn
- nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
- TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
- int thread_index = xc->getSyscallArg(2);
-
- // get attribute args
- attrp.copyIn(xc->port);
-
- if (attrp->version != NXM_LIB_VERSION) {
- cerr << "nxm_thread_create: thread library version mismatch! "
- << "got " << attrp->version
- << ", expected " << NXM_LIB_VERSION << endl;
- abort();
- }
-
- if (thread_index < 0 | thread_index > process->numCpus()) {
- cerr << "nxm_thread_create: bad thread index " << thread_index
- << endl;
- abort();
- }
-
- // On a real machine, the per-RAD shared structure is in
- // shared memory, so both the user and kernel can get at it.
- // We don't have that luxury, so we just copy it in and then
- // back out again.
- int rad_state_size =
- (sizeof(Tru64::nxm_shared) +
- (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
-
- TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
- rad_state_size);
- rad_state.copyIn(xc->port);
-
- uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset;
-
- if (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.copyOut(xc->port);
-
- return 0;
- } else if (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)
- return (int) Tru64::KERN_NOT_RECEIVER;
-
- ssp->nxm_u.pth_id = attrp->pthid;
- ssp->nxm_u.nxm_active = uniq_val | 1;
-
- rad_state.copyOut(xc->port);
-
- Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
- int slot_state_size =
- process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
-
- TypedBufferArg<Tru64::nxm_slot_state_t>
- slot_state(slot_state_addr,
- slot_state_size);
-
- slot_state.copyIn(xc->port);
-
- if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
- cerr << "nxm_thread_createFunc: requested VP slot "
- << thread_index << " not available!" << endl;
- fatal("");
- }
-
- slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
-
- slot_state.copyOut(xc->port);
-
- // Find a free simulator execution context.
- for (int i = 0; i < process->numCpus(); ++i) {
- ExecContext *xc = process->execContexts[i];
-
- if (xc->status() == ExecContext::Unallocated) {
- // inactive context... grab it
- init_exec_context(xc, attrp, uniq_val);
-
- // This is supposed to be a port number, but we'll try
- // and get away with just sticking the thread index
- // here.
- *kidp = thread_index;
- kidp.copyOut(xc->port);
-
- return 0;
- }
- }
-
- // fell out of loop... no available inactive context
- cerr << "nxm_thread_create: no idle contexts available." << endl;
- abort();
- } else {
- cerr << "nxm_thread_create: can't handle thread type "
- << attrp->type << endl;
- abort();
- }
-
- return 0;
- }
-
- /// Thread idle call (like yield()).
- static SyscallReturn
- nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- return 0;
- }
-
- /// Block thread.
- static SyscallReturn
- nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- uint64_t tid = xc->getSyscallArg(0);
- uint64_t secs = xc->getSyscallArg(1);
- uint64_t flags = xc->getSyscallArg(2);
- uint64_t action = xc->getSyscallArg(3);
- uint64_t usecs = xc->getSyscallArg(4);
-
- cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
- << " " << flags << " " << action << " " << usecs << endl;
-
- return 0;
- }
-
- /// block.
- static SyscallReturn
- nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
- uint64_t val = xc->getSyscallArg(1);
- uint64_t secs = xc->getSyscallArg(2);
- uint64_t usecs = xc->getSyscallArg(3);
- uint64_t flags = xc->getSyscallArg(4);
-
- BaseCPU *cpu = xc->cpu;
-
- cout << cpu->name() << ": nxm_block "
- << hex << uaddr << dec << " " << val
- << " " << secs << " " << usecs
- << " " << flags << endl;
-
- return 0;
- }
-
- /// Unblock thread.
- static SyscallReturn
- nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- cout << xc->cpu->name() << ": nxm_unblock "
- << hex << uaddr << dec << endl;
-
- return 0;
- }
-
- /// Switch thread priority.
- static SyscallReturn
- swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- // Attempts to switch to another runnable thread (if there is
- // one). Returns false if there are no other threads to run
- // (i.e., the thread can reasonably spin-wait) or true if there
- // are other threads.
- //
- // Since we assume at most one "kernel" thread per CPU, it's
- // always safe to return false here.
- return 0; //false;
- }
-
-
- /// Activate exec context waiting on a channel. Just activate one
- /// by default.
- static int
- activate_waiting_context(Addr uaddr, Process *process,
- bool activate_all = false)
- {
- int num_activated = 0;
-
- list<Process::WaitRec>::iterator i = process->waitList.begin();
- list<Process::WaitRec>::iterator end = process->waitList.end();
-
- while (i != end && (num_activated == 0 || activate_all)) {
- if (i->waitChan == uaddr) {
- // found waiting process: make it active
- ExecContext *newCtx = i->waitingContext;
- assert(newCtx->status() == ExecContext::Suspended);
- newCtx->activate();
-
- // get rid of this record
- i = process->waitList.erase(i);
-
- ++num_activated;
- } else {
- ++i;
- }
- }
-
- return num_activated;
- }
-
- /// M5 hacked-up lock acquire.
- static void
- m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
- {
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->port);
-
- if (*lockp == 0) {
- // lock is free: grab it
- *lockp = 1;
- lockp.copyOut(xc->port);
- } else {
- // lock is busy: disable until free
- process->waitList.push_back(Process::WaitRec(uaddr, xc));
- xc->suspend();
- }
- }
-
- /// M5 unlock call.
- static void
- m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
- {
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->port);
- assert(*lockp != 0);
-
- // Check for a process waiting on the lock.
- int num_waiting = activate_waiting_context(uaddr, process);
-
- // clear lock field if no waiting context is taking over the lock
- if (num_waiting == 0) {
- *lockp = 0;
- lockp.copyOut(xc->port);
- }
- }
-
- /// Lock acquire syscall handler.
- static SyscallReturn
- m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- m5_lock_mutex(uaddr, process, xc);
-
- // Return 0 since we will always return to the user with the lock
- // acquired. We will just keep the context inactive until that is
- // true.
- return 0;
- }
-
- /// Try lock (non-blocking).
- static SyscallReturn
- m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->port);
-
- if (*lockp == 0) {
- // lock is free: grab it
- *lockp = 1;
- lockp.copyOut(xc->port);
- return 0;
- } else {
- return 1;
- }
- }
-
- /// Unlock syscall handler.
- static SyscallReturn
- m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- m5_unlock_mutex(uaddr, process, xc);
-
- return 0;
- }
-
- /// Signal ocndition.
- static SyscallReturn
- m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
-
- // Wake up one process waiting on the condition variable.
- activate_waiting_context(cond_addr, process);
-
- return 0;
- }
-
- /// Wake up all processes waiting on the condition variable.
- static SyscallReturn
- m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
-
- activate_waiting_context(cond_addr, process, true);
-
- return 0;
- }
-
- /// Wait on a condition.
- static SyscallReturn
- m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
- Addr lock_addr = xc->getSyscallArg(1);
- TypedBufferArg<uint64_t> condp(cond_addr);
- TypedBufferArg<uint64_t> lockp(lock_addr);
-
- // user is supposed to acquire lock before entering
- lockp.copyIn(xc->port);
- assert(*lockp != 0);
-
- m5_unlock_mutex(lock_addr, process, xc);
-
- process->waitList.push_back(Process::WaitRec(cond_addr, xc));
- xc->suspend();
-
- return 0;
- }
-
- /// Thread exit.
- static SyscallReturn
- m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- assert(xc->status() == ExecContext::Active);
- xc->deallocate();
-
- return 0;
- }
-
- /// Array of syscall descriptors for Mach syscalls, indexed by
- /// (negated) call number.
- static SyscallDesc machSyscallDescs[];
-
- /// Number of syscalls in machSyscallDescs[].
- static const int Num_Mach_Syscall_Descs;
-
- /// Max supported Mach syscall number.
- static const int Max_Mach_Syscall_Desc;
-
- /// Since negated values are used to identify Mach syscalls, the
- /// minimum (signed) valid syscall number is the negated max Mach
- /// syscall number.
- static const int Min_Syscall_Desc;
-
- /// Do the specified syscall. Just looks the call number up in
- /// the table and invokes the appropriate handler.
- static void
- doSyscall(int callnum, Process *process, ExecContext *xc)
- {
- if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) {
- fatal("Syscall %d out of range\n", callnum);
- }
-
- SyscallDesc *desc =
- (callnum < 0) ?
- &machSyscallDescs[-callnum] : &syscallDescs[callnum];
-
- desc->doSyscall(callnum, process, xc);
- }
-
- /// Indirect syscall invocation (call #0).
- static SyscallReturn
- indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int new_callnum = xc->getSyscallArg(0);
-
- for (int i = 0; i < 5; ++i)
- xc->setSyscallArg(i, xc->getSyscallArg(i+1));
-
- doSyscall(new_callnum, process, xc);
-
- return 0;
- }
-
-}; // class Tru64
-
-
-// open(2) flags translation table
-OpenFlagTransTable Tru64::openFlagTable[] = {
-#ifdef _MSC_VER
- { Tru64::TGT_O_RDONLY, _O_RDONLY },
- { Tru64::TGT_O_WRONLY, _O_WRONLY },
- { Tru64::TGT_O_RDWR, _O_RDWR },
- { Tru64::TGT_O_APPEND, _O_APPEND },
- { Tru64::TGT_O_CREAT, _O_CREAT },
- { Tru64::TGT_O_TRUNC, _O_TRUNC },
- { Tru64::TGT_O_EXCL, _O_EXCL },
-#ifdef _O_NONBLOCK
- { Tru64::TGT_O_NONBLOCK, _O_NONBLOCK },
-#endif
-#ifdef _O_NOCTTY
- { Tru64::TGT_O_NOCTTY, _O_NOCTTY },
-#endif
-#ifdef _O_SYNC
- { Tru64::TGT_O_SYNC, _O_SYNC },
-#endif
-#else /* !_MSC_VER */
- { Tru64::TGT_O_RDONLY, O_RDONLY },
- { Tru64::TGT_O_WRONLY, O_WRONLY },
- { Tru64::TGT_O_RDWR, O_RDWR },
- { Tru64::TGT_O_APPEND, O_APPEND },
- { Tru64::TGT_O_CREAT, O_CREAT },
- { Tru64::TGT_O_TRUNC, O_TRUNC },
- { Tru64::TGT_O_EXCL, O_EXCL },
- { Tru64::TGT_O_NONBLOCK, O_NONBLOCK },
- { Tru64::TGT_O_NOCTTY, O_NOCTTY },
-#ifdef O_SYNC
- { Tru64::TGT_O_SYNC, O_SYNC },
-#endif
-#endif /* _MSC_VER */
-};
-
-const int Tru64::NUM_OPEN_FLAGS = (sizeof(Tru64::openFlagTable)/sizeof(Tru64::openFlagTable[0]));
-
-const char *Tru64::hostname = "m5.eecs.umich.edu";
-
-SyscallDesc Tru64::syscallDescs[] = {
- /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc,
- SyscallDesc::SuppressReturnValue),
- /* 1 */ SyscallDesc("exit", exitFunc),
- /* 2 */ SyscallDesc("fork", unimplementedFunc),
- /* 3 */ SyscallDesc("read", readFunc),
- /* 4 */ SyscallDesc("write", writeFunc),
- /* 5 */ SyscallDesc("old_open", unimplementedFunc),
- /* 6 */ SyscallDesc("close", closeFunc),
- /* 7 */ SyscallDesc("wait4", unimplementedFunc),
- /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
- /* 9 */ SyscallDesc("link", unimplementedFunc),
- /* 10 */ SyscallDesc("unlink", unlinkFunc),
- /* 11 */ SyscallDesc("execv", unimplementedFunc),
- /* 12 */ SyscallDesc("chdir", unimplementedFunc),
- /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
- /* 14 */ SyscallDesc("mknod", unimplementedFunc),
- /* 15 */ SyscallDesc("chmod", unimplementedFunc),
- /* 16 */ SyscallDesc("chown", unimplementedFunc),
- /* 17 */ SyscallDesc("obreak", obreakFunc),
- /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
- /* 19 */ SyscallDesc("lseek", lseekFunc),
- /* 20 */ SyscallDesc("getpid", getpidFunc),
- /* 21 */ SyscallDesc("mount", unimplementedFunc),
- /* 22 */ SyscallDesc("unmount", unimplementedFunc),
- /* 23 */ SyscallDesc("setuid", setuidFunc),
- /* 24 */ SyscallDesc("getuid", getuidFunc),
- /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
- /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
- /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
- /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
- /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
- /* 30 */ SyscallDesc("accept", unimplementedFunc),
- /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
- /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
- /* 33 */ SyscallDesc("access", unimplementedFunc),
- /* 34 */ SyscallDesc("chflags", unimplementedFunc),
- /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
- /* 36 */ SyscallDesc("sync", unimplementedFunc),
- /* 37 */ SyscallDesc("kill", unimplementedFunc),
- /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
- /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
- /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
- /* 41 */ SyscallDesc("dup", unimplementedFunc),
- /* 42 */ SyscallDesc("pipe", unimplementedFunc),
- /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
- /* 44 */ SyscallDesc("profil", unimplementedFunc),
- /* 45 */ SyscallDesc("open", openFunc<Tru64>),
- /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
- /* 47 */ SyscallDesc("getgid", getgidFunc),
- /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
- /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
- /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
- /* 51 */ SyscallDesc("acct", unimplementedFunc),
- /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
- /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
- /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
- /* 55 */ SyscallDesc("reboot", unimplementedFunc),
- /* 56 */ SyscallDesc("revoke", unimplementedFunc),
- /* 57 */ SyscallDesc("symlink", unimplementedFunc),
- /* 58 */ SyscallDesc("readlink", unimplementedFunc),
- /* 59 */ SyscallDesc("execve", unimplementedFunc),
- /* 60 */ SyscallDesc("umask", unimplementedFunc),
- /* 61 */ SyscallDesc("chroot", unimplementedFunc),
- /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
- /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
- /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
- /* 65 */ SyscallDesc("mremap", unimplementedFunc),
- /* 66 */ SyscallDesc("vfork", unimplementedFunc),
- /* 67 */ SyscallDesc("pre_F64_stat", statFunc<Tru64::PreF64>),
- /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<Tru64::PreF64>),
- /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
- /* 70 */ SyscallDesc("sstk", unimplementedFunc),
- /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
- /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
- /* 73 */ SyscallDesc("munmap", munmapFunc),
- /* 74 */ SyscallDesc("mprotect", ignoreFunc),
- /* 75 */ SyscallDesc("madvise", unimplementedFunc),
- /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
- /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
- /* 78 */ SyscallDesc("mincore", unimplementedFunc),
- /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
- /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
- /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
- /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
- /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
- /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
- /* 85 */ SyscallDesc("table", tableFunc),
- /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
- /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
- /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
- /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
- /* 90 */ SyscallDesc("dup2", unimplementedFunc),
- /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<Tru64::PreF64>),
- /* 92 */ SyscallDesc("fcntl", fcntlFunc),
- /* 93 */ SyscallDesc("select", unimplementedFunc),
- /* 94 */ SyscallDesc("poll", unimplementedFunc),
- /* 95 */ SyscallDesc("fsync", unimplementedFunc),
- /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
- /* 97 */ SyscallDesc("socket", unimplementedFunc),
- /* 98 */ SyscallDesc("connect", unimplementedFunc),
- /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
- /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
- /* 101 */ SyscallDesc("old_send", unimplementedFunc),
- /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
- /* 103 */ SyscallDesc("sigreturn", sigreturnFunc,
- SyscallDesc::SuppressReturnValue),
- /* 104 */ SyscallDesc("bind", unimplementedFunc),
- /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
- /* 106 */ SyscallDesc("listen", unimplementedFunc),
- /* 107 */ SyscallDesc("plock", unimplementedFunc),
- /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
- /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
- /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
- /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
- /* 112 */ SyscallDesc("sigstack", ignoreFunc),
- /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
- /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
- /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
- /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>),
- /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>),
- /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
- /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
- /* 120 */ SyscallDesc("readv", unimplementedFunc),
- /* 121 */ SyscallDesc("writev", unimplementedFunc),
- /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
- /* 123 */ SyscallDesc("fchown", unimplementedFunc),
- /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
- /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
- /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
- /* 127 */ SyscallDesc("setregid", unimplementedFunc),
- /* 128 */ SyscallDesc("rename", renameFunc),
- /* 129 */ SyscallDesc("truncate", truncateFunc),
- /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
- /* 131 */ SyscallDesc("flock", unimplementedFunc),
- /* 132 */ SyscallDesc("setgid", unimplementedFunc),
- /* 133 */ SyscallDesc("sendto", unimplementedFunc),
- /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
- /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
- /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
- /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
- /* 138 */ SyscallDesc("utimes", unimplementedFunc),
- /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
- /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
- /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
- /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
- /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
- /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
- /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
- /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
- /* 147 */ SyscallDesc("setsid", unimplementedFunc),
- /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
- /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
- /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
- /* 151 */ SyscallDesc("pread", unimplementedFunc),
- /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
- /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
- /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
- /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
- /* 156 */ SyscallDesc("sigaction", ignoreFunc),
- /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
- /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
- /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc),
- /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>),
- /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>),
- /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
- /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
- /* 164 */ SyscallDesc("getfh", unimplementedFunc),
- /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
- /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
- /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
- /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
- /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
- /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
- /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
- /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
- /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
- /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
- /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
- /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
- /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
- /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
- /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
- /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
- /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
- /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
- /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
- /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
- /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
- /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
- /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
- /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
- /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
- /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
- /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
- /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
- /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
- /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
- /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
- /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
- /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
- /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
- /* 199 */ SyscallDesc("swapon", unimplementedFunc),
- /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
- /* 201 */ SyscallDesc("msgget", unimplementedFunc),
- /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
- /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
- /* 204 */ SyscallDesc("semctl", unimplementedFunc),
- /* 205 */ SyscallDesc("semget", unimplementedFunc),
- /* 206 */ SyscallDesc("semop", unimplementedFunc),
- /* 207 */ SyscallDesc("uname", unameFunc),
- /* 208 */ SyscallDesc("lchown", unimplementedFunc),
- /* 209 */ SyscallDesc("shmat", unimplementedFunc),
- /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
- /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
- /* 212 */ SyscallDesc("shmget", unimplementedFunc),
- /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
- /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
- /* 215 */ SyscallDesc("msleep", unimplementedFunc),
- /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
- /* 217 */ SyscallDesc("msync", unimplementedFunc),
- /* 218 */ SyscallDesc("signal", unimplementedFunc),
- /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
- /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
- /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
- /* 222 */ SyscallDesc("security", unimplementedFunc),
- /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
- /* 224 */ SyscallDesc("stat", statFunc<Tru64::F64>),
- /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64::F64>),
- /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64::F64>),
- /* 227 */ SyscallDesc("statfs", statfsFunc<Tru64::F64>),
- /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<Tru64::F64>),
- /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
- /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
- /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
- /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
- /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
- /* 234 */ SyscallDesc("getsid", unimplementedFunc),
- /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
- /* 236 */ SyscallDesc("waitid", unimplementedFunc),
- /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
- /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
- /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
- /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
- /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
- /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
- /* 243 */ SyscallDesc("fuser", unimplementedFunc),
- /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
- /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
- /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
- /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
- /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
- /* 249 */ SyscallDesc("sync2", unimplementedFunc),
- /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
- /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
- /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
- /* 253 */ SyscallDesc("audgen", unimplementedFunc),
- /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
- /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
- /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
- /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc),
- /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
- /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
- /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
- /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
- /* 262 */ SyscallDesc("oflock", unimplementedFunc),
- /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
- /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
- /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
- /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
-};
-
-const int Tru64::Num_Syscall_Descs =
- sizeof(Tru64::syscallDescs) / sizeof(SyscallDesc);
-
-const int Tru64::Max_Syscall_Desc = Tru64::Num_Syscall_Descs - 1;
-
-SyscallDesc Tru64::machSyscallDescs[] = {
- /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 1 */ SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc),
- /* 2 */ SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc),
- /* 3 */ SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc),
- /* 4 */ SyscallDesc("m5_cond_signal", m5_cond_signalFunc),
- /* 5 */ SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc),
- /* 6 */ SyscallDesc("m5_cond_wait", m5_cond_waitFunc),
- /* 7 */ SyscallDesc("m5_thread_exit", m5_thread_exitFunc),
- /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 10 */ SyscallDesc("task_self", unimplementedFunc),
- /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
- /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
- /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
- /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
- /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
- /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
- /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc),
- /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc),
- /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
- /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
- /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
- /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc),
- /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc),
- /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc),
- /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
- /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
- /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
- /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc),
- /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
- /* 41 */ SyscallDesc("init_process", unimplementedFunc),
- /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
- /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
- /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
- /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
- /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
- /* 47 */ SyscallDesc("stack_create", stack_createFunc),
- /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
- /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
- /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
- /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
- /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
- /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 55 */ SyscallDesc("host_self", unimplementedFunc),
- /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
- /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc),
- /* 60 */ SyscallDesc("swtch", unimplementedFunc),
- /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
- /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
- /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
- /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
- /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
- /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
- /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc),
- /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
- /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
- /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
- /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
- /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
- /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
- /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
- /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
- /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
- /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
- /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
- /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
- /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
- /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
-};
-
-const int Tru64::Num_Mach_Syscall_Descs =
- sizeof(Tru64::machSyscallDescs) / sizeof(SyscallDesc);
-const int Tru64::Max_Mach_Syscall_Desc = Tru64::Num_Mach_Syscall_Descs - 1;
-const int Tru64::Min_Syscall_Desc = -Tru64::Max_Mach_Syscall_Desc;
-
-
-void
-AlphaTru64Process::syscall(ExecContext *xc)
-{
- num_syscalls++;
-
- int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
-
- Tru64::doSyscall(callnum, this, xc);
-}
-
-
-AlphaTru64Process::AlphaTru64Process(const std::string &name,
- ObjectFile *objFile,
- System *system,
- int stdin_fd,
- int stdout_fd,
- int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp)
- : LiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd,
- argv, envp)
-{
-}
diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc
index a340a2053..019390aeb 100644
--- a/arch/alpha/arguments.cc
+++ b/arch/alpha/arguments.cc
@@ -31,6 +31,8 @@
#include "cpu/exec_context.hh"
#include "mem/functional/physical.hh"
+using namespace AlphaISA;
+
AlphaArguments::Data::~Data()
{
while (!data.empty()) {
@@ -52,13 +54,13 @@ AlphaArguments::getArg(bool fp)
{
if (number < 6) {
if (fp)
- return xc->regs.floatRegFile.q[16 + number];
+ return xc->readFloatRegInt(16 + number);
else
- return xc->regs.intRegFile[16 + number];
+ return xc->readIntReg(16 + number);
} else {
- Addr sp = xc->regs.intRegFile[30];
+ Addr sp = xc->readIntReg(30);
Addr paddr = vtophys(xc, sp + (number-6) * sizeof(uint64_t));
- return xc->physmem->phys_read_qword(paddr);
+ return xc->getPhysMemPtr()->phys_read_qword(paddr);
}
}
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 125affd03..019e83dd4 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -26,7 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "arch/alpha/alpha_memory.hh"
+#include "arch/alpha/tlb.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/osfpal.hh"
#include "base/kgdb.h"
@@ -34,6 +34,7 @@
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast/cpu.hh"
#include "kern/kernel_stats.hh"
@@ -46,83 +47,34 @@ using namespace EV5;
////////////////////////////////////////////////////////////////////////
//
-//
-//
-void
-AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow)
-{
- if (regs->pal_shadow == use_shadow)
- panic("swap_palshadow: wrong PAL shadow state");
-
- regs->pal_shadow = use_shadow;
-
- for (int i = 0; i < NumIntRegs; i++) {
- if (reg_redir[i]) {
- IntReg temp = regs->intRegFile[i];
- regs->intRegFile[i] = regs->palregs[i];
- regs->palregs[i] = temp;
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-//
// Machine dependent functions
//
void
-AlphaISA::initCPU(RegFile *regs)
+AlphaISA::initCPU(ExecContext *xc, int cpuId)
{
- initIPRs(regs);
- // CPU comes up with PAL regs enabled
- swap_palshadow(regs, true);
+ initIPRs(xc, cpuId);
- regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault];
- regs->npc = regs->pc + sizeof(MachInst);
-}
+ xc->setIntReg(16, cpuId);
+ xc->setIntReg(0, cpuId);
-////////////////////////////////////////////////////////////////////////
-//
-// 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 int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
- /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
- /* 8 */ 1, 1, 1, 1, 1, 1, 1, 0,
- /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0,
- /* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 };
+ xc->setPC(xc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
+}
////////////////////////////////////////////////////////////////////////
//
//
//
void
-AlphaISA::initIPRs(RegFile *regs)
+AlphaISA::initIPRs(ExecContext *xc, int cpuId)
{
- uint64_t *ipr = regs->ipr;
+ for (int i = 0; i < NumInternalProcRegs; ++i) {
+ xc->setMiscReg(i, 0);
+ }
- bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
- ipr[IPR_PAL_BASE] = PalBase;
- ipr[IPR_MCSR] = 0x6;
+ xc->setMiscReg(IPR_PAL_BASE, PalBase);
+ xc->setMiscReg(IPR_MCSR, 0x6);
+ xc->setMiscReg(IPR_PALtemp16, cpuId);
}
@@ -134,17 +86,16 @@ AlphaISA::processInterrupts(CPU *cpu)
//Handle the interrupts
int ipl = 0;
int summary = 0;
- IntReg *ipr = cpu->getIprPtr();
cpu->checkInterrupts = false;
- if (ipr[IPR_ASTRR])
+ if (cpu->readMiscReg(IPR_ASTRR))
panic("asynchronous traps not implemented\n");
- if (ipr[IPR_SIRR]) {
+ if (cpu->readMiscReg(IPR_SIRR)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (ipr[IPR_SIRR] & (ULL(1) << i)) {
+ if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
@@ -165,12 +116,12 @@ AlphaISA::processInterrupts(CPU *cpu)
}
}
- if (ipl && ipl > ipr[IPR_IPLR]) {
- ipr[IPR_ISR] = summary;
- ipr[IPR_INTID] = ipl;
- cpu->trap(Interrupt_Fault);
+ if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
+ cpu->setMiscReg(IPR_ISR, summary);
+ cpu->setMiscReg(IPR_INTID, ipl);
+ cpu->trap(new InterruptFault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- ipr[IPR_IPLR], ipl, summary);
+ cpu->readMiscReg(IPR_IPLR), ipl, summary);
}
}
@@ -182,96 +133,43 @@ AlphaISA::zeroRegisters(CPU *cpu)
// Insure ISA semantics
// (no longer very clean due to the change in setIntReg() in the
// cpu model. Consider changing later.)
- cpu->xc->setIntReg(ZeroReg, 0);
- cpu->xc->setFloatRegDouble(ZeroReg, 0.0);
+ cpu->cpuXC->setIntReg(ZeroReg, 0);
+ cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0);
}
-void
-ExecContext::ev5_trap(Fault fault)
+Fault
+CPUExecContext::hwrei()
{
- DPRINTF(Fault, "Fault %s at PC: %#x\n", FaultName(fault), regs.pc);
- cpu->recordEvent(csprintf("Fault %s", FaultName(fault)));
-
- assert(!misspeculating());
- kernelStats->fault(fault);
-
- if (fault == Arithmetic_Fault)
- panic("Arithmetic traps are unimplemented!");
+ if (!inPalMode())
+ return new UnimplementedOpcodeFault;
- AlphaISA::InternalProcReg *ipr = regs.ipr;
+ setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
- // exception restart address
- if (fault != Interrupt_Fault || !inPalMode())
- ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
+ if (!misspeculating()) {
+ cpu->kernelStats->hwrei();
- if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
- fault == Interrupt_Fault && !inPalMode() */) {
- // traps... skip faulting instruction
- ipr[AlphaISA::IPR_EXC_ADDR] += 4;
+ cpu->checkInterrupts = true;
}
- if (!inPalMode())
- AlphaISA::swap_palshadow(&regs, true);
-
- regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
- regs.npc = regs.pc + sizeof(MachInst);
+ // FIXME: XXX check for interrupts? XXX
+ return NoFault;
}
-
-void
-AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
+int
+AlphaISA::MiscRegFile::getInstAsid()
{
- InternalProcReg *ipr = regs->ipr;
- bool use_pc = (fault == No_Fault);
-
- if (fault == Arithmetic_Fault)
- panic("arithmetic faults NYI...");
-
- // compute exception restart address
- if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) {
- // traps... skip faulting instruction
- ipr[IPR_EXC_ADDR] = regs->pc + 4;
- } else {
- // fault, post fault at excepting instruction
- ipr[IPR_EXC_ADDR] = regs->pc;
- }
-
- // jump to expection address (PAL PC bit set here as well...)
- if (!use_pc)
- 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)
+ return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
}
-Fault
-ExecContext::hwrei()
+int
+AlphaISA::MiscRegFile::getDataAsid()
{
- uint64_t *ipr = regs.ipr;
-
- if (!inPalMode())
- return Unimplemented_Opcode_Fault;
-
- setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
-
- if (!misspeculating()) {
- kernelStats->hwrei();
-
- if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
- AlphaISA::swap_palshadow(&regs, false);
-
- cpu->checkInterrupts = true;
- }
-
- // FIXME: XXX check for interrupts? XXX
- return No_Fault;
+ return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
}
-uint64_t
-ExecContext::readIpr(int idx, Fault &fault)
+AlphaISA::MiscReg
+AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ExecContext *xc)
{
- uint64_t *ipr = regs.ipr;
uint64_t retval = 0; // return value, default 0
switch (idx) {
@@ -324,7 +222,7 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_CC:
retval |= ipr[idx] & ULL(0xffffffff00000000);
- retval |= cpu->curCycle() & ULL(0x00000000ffffffff);
+ retval |= xc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
break;
case AlphaISA::IPR_VA:
@@ -341,7 +239,7 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_DTB_PTE:
{
- AlphaISA::PTE &pte = dtb->index(!misspeculating());
+ AlphaISA::PTE &pte = xc->getDTBPtr()->index(!xc->misspeculating());
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
@@ -363,12 +261,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 = new UnimplementedOpcodeFault;
break;
default:
// invalid IPR
- fault = Unimplemented_Opcode_Fault;
+ fault = new UnimplementedOpcodeFault;
break;
}
@@ -381,13 +279,12 @@ int break_ipl = -1;
#endif
Fault
-ExecContext::setIpr(int idx, uint64_t val)
+AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc)
{
- uint64_t *ipr = regs.ipr;
uint64_t old;
- if (misspeculating())
- return No_Fault;
+ if (xc->misspeculating())
+ return NoFault;
switch (idx) {
case AlphaISA::IPR_PALtemp0:
@@ -439,7 +336,7 @@ ExecContext::setIpr(int idx, uint64_t val)
// write entire quad w/ no side-effect
old = ipr[idx];
ipr[idx] = val;
- kernelStats->context(old, val);
+ xc->getCpuPtr()->kernelStats->context(old, val, xc);
break;
case AlphaISA::IPR_DTB_PTE:
@@ -466,14 +363,14 @@ ExecContext::setIpr(int idx, uint64_t val)
// only write least significant five bits - interrupt level
ipr[idx] = val & 0x1f;
- kernelStats->swpipl(ipr[idx]);
+ xc->getCpuPtr()->kernelStats->swpipl(ipr[idx]);
break;
case AlphaISA::IPR_DTB_CM:
if (val & 0x18)
- kernelStats->mode(Kernel::user);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::user, xc);
else
- kernelStats->mode(Kernel::kernel);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc);
case AlphaISA::IPR_ICM:
// only write two mode bits - processor mode
@@ -533,7 +430,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 new UnimplementedOpcodeFault;
case AlphaISA::IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT:
@@ -547,21 +444,22 @@ ExecContext::setIpr(int idx, uint64_t val)
// really a control write
ipr[idx] = 0;
- dtb->flushAll();
+ xc->getDTBPtr()->flushAll();
break;
case AlphaISA::IPR_DTB_IAP:
// really a control write
ipr[idx] = 0;
- dtb->flushProcesses();
+ xc->getDTBPtr()->flushProcesses();
break;
case AlphaISA::IPR_DTB_IS:
// really a control write
ipr[idx] = val;
- dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ xc->getDTBPtr()->flushAddr(val,
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
break;
case AlphaISA::IPR_DTB_TAG: {
@@ -584,7 +482,7 @@ ExecContext::setIpr(int idx, uint64_t val)
pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
// insert new TAG/PTE value into data TLB
- dtb->insert(val, pte);
+ xc->getDTBPtr()->insert(val, pte);
}
break;
@@ -608,7 +506,7 @@ ExecContext::setIpr(int idx, uint64_t val)
pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
// insert new TAG/PTE value into data TLB
- itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
+ xc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
}
break;
@@ -616,30 +514,39 @@ ExecContext::setIpr(int idx, uint64_t val)
// really a control write
ipr[idx] = 0;
- itb->flushAll();
+ xc->getITBPtr()->flushAll();
break;
case AlphaISA::IPR_ITB_IAP:
// really a control write
ipr[idx] = 0;
- itb->flushProcesses();
+ xc->getITBPtr()->flushProcesses();
break;
case AlphaISA::IPR_ITB_IS:
// really a control write
ipr[idx] = val;
- itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
+ xc->getITBPtr()->flushAddr(val,
+ ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
break;
default:
// invalid IPR
- return Unimplemented_Opcode_Fault;
+ return new UnimplementedOpcodeFault;
}
// no error...
- return No_Fault;
+ return NoFault;
+}
+
+void
+AlphaISA::MiscRegFile::copyIprs(ExecContext *xc)
+{
+ for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) {
+ ipr[i] = xc->readMiscReg(i);
+ }
}
/**
@@ -647,9 +554,9 @@ ExecContext::setIpr(int idx, uint64_t val)
* If return value is false, actual PAL call will be suppressed.
*/
bool
-ExecContext::simPalCheck(int palFunc)
+CPUExecContext::simPalCheck(int palFunc)
{
- kernelStats->callpal(palFunc);
+ cpu->kernelStats->callpal(palFunc, proxy);
switch (palFunc) {
case PAL::halt:
diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh
index 5173b364f..7c8465cfb 100644
--- a/arch/alpha/ev5.hh
+++ b/arch/alpha/ev5.hh
@@ -30,9 +30,13 @@
#define __ARCH_ALPHA_EV5_HH__
#include "config/alpha_tlaser.hh"
+#include "arch/alpha/isa_traits.hh"
namespace EV5 {
+//It seems like a safe assumption EV5 only applies to alpha
+using namespace AlphaISA;
+
#if ALPHA_TLASER
const uint64_t AsnMask = ULL(0x7f);
#else
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc
index 3aecf029d..e0918da21 100644
--- a/arch/alpha/faults.cc
+++ b/arch/alpha/faults.cc
@@ -27,35 +27,105 @@
*/
#include "arch/alpha/faults.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "base/trace.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",
- };
-}
+namespace AlphaISA
+{
+
+FaultName MachineCheckFault::_name = "mchk";
+FaultVect MachineCheckFault::_vect = 0x0401;
+FaultStat MachineCheckFault::_count;
+
+FaultName AlignmentFault::_name = "unalign";
+FaultVect AlignmentFault::_vect = 0x0301;
+FaultStat AlignmentFault::_count;
+
+FaultName ResetFault::_name = "reset";
+FaultVect ResetFault::_vect = 0x0001;
+FaultStat ResetFault::_count;
+
+FaultName ArithmeticFault::_name = "arith";
+FaultVect ArithmeticFault::_vect = 0x0501;
+FaultStat ArithmeticFault::_count;
+
+FaultName InterruptFault::_name = "interrupt";
+FaultVect InterruptFault::_vect = 0x0101;
+FaultStat InterruptFault::_count;
+
+FaultName NDtbMissFault::_name = "dtb_miss_single";
+FaultVect NDtbMissFault::_vect = 0x0201;
+FaultStat NDtbMissFault::_count;
+
+FaultName PDtbMissFault::_name = "dtb_miss_double";
+FaultVect PDtbMissFault::_vect = 0x0281;
+FaultStat PDtbMissFault::_count;
+
+FaultName DtbPageFault::_name = "dfault";
+FaultVect DtbPageFault::_vect = 0x0381;
+FaultStat DtbPageFault::_count;
+
+FaultName DtbAcvFault::_name = "dfault";
+FaultVect DtbAcvFault::_vect = 0x0381;
+FaultStat DtbAcvFault::_count;
+
+FaultName ItbMissFault::_name = "itbmiss";
+FaultVect ItbMissFault::_vect = 0x0181;
+FaultStat ItbMissFault::_count;
+
+FaultName ItbPageFault::_name = "itbmiss";
+FaultVect ItbPageFault::_vect = 0x0181;
+FaultStat ItbPageFault::_count;
-const char *
-FaultName(int index)
+FaultName ItbAcvFault::_name = "iaccvio";
+FaultVect ItbAcvFault::_vect = 0x0081;
+FaultStat ItbAcvFault::_count;
+
+FaultName UnimplementedOpcodeFault::_name = "opdec";
+FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
+FaultStat UnimplementedOpcodeFault::_count;
+
+FaultName FloatEnableFault::_name = "fen";
+FaultVect FloatEnableFault::_vect = 0x0581;
+FaultStat FloatEnableFault::_count;
+
+FaultName PalFault::_name = "pal";
+FaultVect PalFault::_vect = 0x2001;
+FaultStat PalFault::_count;
+
+FaultName IntegerOverflowFault::_name = "intover";
+FaultVect IntegerOverflowFault::_vect = 0x0501;
+FaultStat IntegerOverflowFault::_count;
+
+#if FULL_SYSTEM
+
+void AlphaFault::invoke(ExecContext * xc)
{
- if (index < 0 || index >= Num_Faults)
- return 0;
+ FaultBase::invoke(xc);
+ countStat()++;
+
+ // exception restart address
+ if (setRestartAddress() || !xc->inPalMode())
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, xc->readPC());
- return fault_name[index];
+ if (skipFaultingInstruction()) {
+ // traps... skip faulting instruction.
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
+ xc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
+ }
+
+ xc->setPC(xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect());
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
+}
+
+void ArithmeticFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ panic("Arithmetic traps are unimplemented!");
}
+#endif
+
+} // namespace AlphaISA
+
diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh
index bbac7cbf2..1a196cc94 100644
--- a/arch/alpha/faults.hh
+++ b/arch/alpha/faults.hh
@@ -26,32 +26,244 @@
* 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
-};
-
-const char *
-FaultName(int index);
+#ifndef __ALPHA_FAULTS_HH__
+#define __ALPHA_FAULTS_HH__
+
+#include "sim/faults.hh"
+
+// The design of the "name" and "vect" functions is in sim/faults.hh
+
+namespace AlphaISA
+{
+
+typedef const Addr FaultVect;
+
+class AlphaFault : public FaultBase
+{
+ protected:
+ virtual bool skipFaultingInstruction() {return false;}
+ virtual bool setRestartAddress() {return true;}
+ public:
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+ virtual FaultVect vect() = 0;
+ virtual FaultStat & countStat() = 0;
+};
+
+class MachineCheckFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+ bool isMachineCheckFault() {return true;}
+};
+
+class AlignmentFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+ bool isAlignmentFault() {return true;}
+};
+
+static inline Fault genMachineCheckFault()
+{
+ return new MachineCheckFault;
+}
+
+static inline Fault genAlignmentFault()
+{
+ return new AlignmentFault;
+}
+
+class ResetFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ArithmeticFault : public AlphaFault
+{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class InterruptFault : public AlphaFault
+{
+ protected:
+ bool setRestartAddress() {return false;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class NDtbMissFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PDtbMissFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbPageFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbAcvFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbMissFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbPageFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbAcvFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedOpcodeFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FloatEnableFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PalFault : public AlphaFault
+{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class IntegerOverflowFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+} // AlphaISA namespace
#endif // __FAULTS_HH__
diff --git a/kern/freebsd/freebsd_system.cc b/arch/alpha/freebsd/system.cc
index 283713d40..e32053afd 100644
--- a/kern/freebsd/freebsd_system.cc
+++ b/arch/alpha/freebsd/system.cc
@@ -33,20 +33,24 @@
*
*/
+#include "arch/alpha/system.hh"
+#include "arch/alpha/freebsd/system.hh"
#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh"
-#include "kern/freebsd/freebsd_system.hh"
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
+#include "arch/isa_traits.hh"
#include "sim/builder.hh"
-#include "targetarch/vtophys.hh"
+#include "sim/byteswap.hh"
+#include "arch/vtophys.hh"
#define TIMER_FREQUENCY 1193180
using namespace std;
+using namespace AlphaISA;
-FreebsdSystem::FreebsdSystem(Params *p)
- : System(p)
+FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
+ : AlphaSystem(p)
{
/**
* Any time DELAY is called just skip the function.
@@ -58,7 +62,7 @@ FreebsdSystem::FreebsdSystem(Params *p)
}
-FreebsdSystem::~FreebsdSystem()
+FreebsdAlphaSystem::~FreebsdAlphaSystem()
{
delete skipDelayEvent;
delete skipCalibrateClocks;
@@ -66,15 +70,15 @@ FreebsdSystem::~FreebsdSystem()
void
-FreebsdSystem::doCalibrateClocks(ExecContext *xc)
+FreebsdAlphaSystem::doCalibrateClocks(ExecContext *xc)
{
Addr ppc_vaddr = 0;
Addr timer_vaddr = 0;
Addr ppc_paddr = 0;
Addr timer_paddr = 0;
- ppc_vaddr = (Addr)xc->regs.intRegFile[ArgumentReg1];
- timer_vaddr = (Addr)xc->regs.intRegFile[ArgumentReg2];
+ ppc_vaddr = (Addr)xc->readIntReg(ArgumentReg1);
+ timer_vaddr = (Addr)xc->readIntReg(ArgumentReg2);
ppc_paddr = vtophys(physmem, ppc_vaddr);
timer_paddr = vtophys(physmem, timer_vaddr);
@@ -88,14 +92,14 @@ FreebsdSystem::doCalibrateClocks(ExecContext *xc)
void
-FreebsdSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
+FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
{
SkipFuncEvent::process(xc);
- ((FreebsdSystem *)xc->system)->doCalibrateClocks(xc);
+ ((FreebsdAlphaSystem *)xc->getSystemPtr())->doCalibrateClocks(xc);
}
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdSystem)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<MemoryController *> memctrl;
@@ -116,9 +120,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdSystem)
VectorParam<string> binned_fns;
Param<bool> bin_int;
-END_DECLARE_SIM_OBJECT_PARAMS(FreebsdSystem)
+END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
-BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdSystem)
+BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(memctrl, "memory controller"),
@@ -136,11 +140,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdSystem)
INIT_PARAM(binned_fns, "functions to be broken down and binned"),
INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
-END_INIT_SIM_OBJECT_PARAMS(FreebsdSystem)
+END_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
-CREATE_SIM_OBJECT(FreebsdSystem)
+CREATE_SIM_OBJECT(FreebsdAlphaSystem)
{
- System::Params *p = new System::Params;
+ AlphaSystem::Params *p = new AlphaSystem::Params;
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->memctrl = memctrl;
@@ -156,8 +160,8 @@ CREATE_SIM_OBJECT(FreebsdSystem)
p->bin = bin;
p->binned_fns = binned_fns;
p->bin_int = bin_int;
- return new FreebsdSystem(p);
+ return new FreebsdAlphaSystem(p);
}
-REGISTER_SIM_OBJECT("FreebsdSystem", FreebsdSystem)
+REGISTER_SIM_OBJECT("FreebsdAlphaSystem", FreebsdAlphaSystem)
diff --git a/kern/freebsd/freebsd_system.hh b/arch/alpha/freebsd/system.hh
index ecb842ec6..5d996955e 100644
--- a/kern/freebsd/freebsd_system.hh
+++ b/arch/alpha/freebsd/system.hh
@@ -31,7 +31,7 @@
#include "kern/system_events.hh"
-class FreebsdSystem : public System
+class FreebsdAlphaSystem : public AlphaSystem
{
private:
class SkipCalibrateClocksEvent : public SkipFuncEvent
@@ -47,8 +47,8 @@ class FreebsdSystem : public System
SkipCalibrateClocksEvent *skipCalibrateClocks;
public:
- FreebsdSystem(Params *p);
- ~FreebsdSystem();
+ FreebsdAlphaSystem(Params *p);
+ ~FreebsdAlphaSystem();
void doCalibrateClocks(ExecContext *xc);
};
diff --git a/arch/alpha/isa/branch.isa b/arch/alpha/isa/branch.isa
new file mode 100644
index 000000000..b528df938
--- /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, ExtMachInst _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, ExtMachInst _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, ExtMachInst _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 *)new %(class_name)s(machInst)
+ : (StaticInst *)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..e09673269
--- /dev/null
+++ b/arch/alpha/isa/decoder.isa
@@ -0,0 +1,819 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2006 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+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 = new 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 = new 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 = new 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 = new 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 = new 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 = new 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 = new ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+#else
+ 0x0b: sqrts({{
+ if (Fb.sf < 0.0)
+ fault = new ArithmeticFault;
+ Fc.sf = sqrt(Fb.sf);
+ }}, FloatSqrtOp);
+#endif
+ 0x2b: sqrtt({{
+ if (Fb < 0.0)
+ fault = new 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 = new 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->readMiscRegWithEffect(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->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
+ // invalid pal function code, or attempt to do privileged
+ // PAL call in non-kernel mode
+ fault = new 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) {
+ xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC);
+ NPC = xc->readMiscRegWithEffect(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
+ 0x1b: decode PALMODE {
+ 0: OpcdecFault::hw_st_quad();
+ 1: decode HW_LDST_QUAD {
+ format HwLoad {
+ 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
+ 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
+ }
+ }
+ }
+
+ 0x1f: decode PALMODE {
+ 0: OpcdecFault::hw_st_cond();
+ format HwStore {
+ 1: 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();
+ }
+ }
+ }
+
+ 0x19: decode PALMODE {
+ 0: OpcdecFault::hw_mfpr();
+ format HwMoveIPR {
+ 1: hw_mfpr({{
+ Ra = xc->readMiscRegWithEffect(ipr_index, fault);
+ }});
+ }
+ }
+
+ 0x1d: decode PALMODE {
+ 0: OpcdecFault::hw_mtpr();
+ format HwMoveIPR {
+ 1: hw_mtpr({{
+ xc->setMiscRegWithEffect(ipr_index, Ra);
+ if (traceData) { traceData->setData(Ra); }
+ }});
+ }
+ }
+
+ format BasicOperate {
+ 0x1e: decode PALMODE {
+ 0: OpcdecFault::hw_rei();
+ 1: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);
+ 0x02: quiesceNs({{
+ AlphaPseudo::quiesceNs(xc->xcBase(), R16);
+ }}, IsNonSpeculative);
+ 0x03: quiesceCycles({{
+ AlphaPseudo::quiesceCycles(xc->xcBase(), R16);
+ }}, IsNonSpeculative);
+ 0x04: quiesceTime({{
+ R0 = AlphaPseudo::quiesceTime(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()->getCpuPtr()->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);
+ 0x54: m5panic({{
+ panic("M5 panic instruction called.");
+ }}, IsNonSpeculative);
+
+ }
+ }
+#endif
+}
diff --git a/arch/alpha/isa/fp.isa b/arch/alpha/isa/fp.isa
new file mode 100644
index 000000000..f34c13c42
--- /dev/null
+++ b/arch/alpha/isa/fp.isa
@@ -0,0 +1,301 @@
+// -*- 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->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) {
+ fault = new 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, ExtMachInst _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->readMiscReg(AlphaISA::Fpcr_DepTag)));
+ %(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..17ecc1a51
--- /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, ExtMachInst _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..d4c744fbc
--- /dev/null
+++ b/arch/alpha/isa/main.isa
@@ -0,0 +1,448 @@
+// -*- 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/request.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>
+
+using namespace AlphaISA;
+}};
+
+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"
+
+using namespace AlphaISA;
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// AlphaISAInst namespace.
+//
+
+
+namespace AlphaISA;
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Universal (format-independent) fields
+def bitfield PALMODE <32:32>;
+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', 'PALMODE ? AlphaISA::reg_redir[RA] : RA',
+ 'IsInteger', 1),
+ 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB',
+ 'IsInteger', 2),
+ 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : 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', 'TheISA::Uniq_DepTag', None, 1),
+ 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', 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
+ {
+ 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,
+ Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag,
+ Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag,
+ IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
+ };
+
+ /// Constructor.
+ AlphaStaticInst(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : StaticInst(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(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst 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, ExtMachInst _machInst)
+ : AlphaStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ flags[IsNop] = true;
+ }
+
+ ~Nop() { }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ %(BasicExecDeclare)s
+ };
+
+ /// Helper function for decoding nops. Substitute Nop object
+ /// for original inst passed in as arg (and delete latter).
+ static inline
+ AlphaStaticInst *
+ makeNop(AlphaStaticInst *inst)
+ {
+ AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
+ delete inst;
+ return nop;
+ }
+}};
+
+output decoder {{
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return originalDisassembly;
+#else
+ return csprintf("%-10s (%s)", "nop", originalDisassembly);
+#endif
+ }
+}};
+
+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"
+
+// Opcdec fault instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/opcdec.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..3c8b4f755
--- /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 eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ /// Constructor
+ Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr &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, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _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, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _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(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ MemAcc(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ public:
+
+ /// Constructor.
+ %(class_name)s(ExtMachInst 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(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
+ {
+ %(ea_constructor)s;
+ }
+
+ inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(ExtMachInst 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/opcdec.isa b/arch/alpha/isa/opcdec.isa
new file mode 100644
index 000000000..bb2f91e5c
--- /dev/null
+++ b/arch/alpha/isa/opcdec.isa
@@ -0,0 +1,72 @@
+// -*- 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 instructions that cause an OPCDEC fault
+ * when executed. This is currently only for PAL mode instructions
+ * executed in non-PAL mode.
+ */
+ class OpcdecFault : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ OpcdecFault(ExtMachInst _machInst)
+ : AlphaStaticInst("opcdec fault", _machInst, No_OpClass)
+ {
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ OpcdecFault::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+ " OPCDEC fault", machInst, OPCODE);
+ }
+}};
+
+output exec {{
+ Fault
+ OpcdecFault::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format OpcdecFault() {{
+ decode_block = 'return new OpcdecFault(machInst);\n'
+}};
+
diff --git a/arch/alpha/isa/pal.isa b/arch/alpha/isa/pal.isa
new file mode 100644
index 000000000..e07bea5a8
--- /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, ExtMachInst _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, ExtMachInst _machInst,
+ OpClass __opClass);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ inline
+ CallPalBase::CallPalBase(const char *mnem, ExtMachInst _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, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ inline
+ HwLoadStore::HwLoadStore(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass,
+ StaticInstPtr _eaCompPtr,
+ StaticInstPtr _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, ExtMachInst _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..392522801
--- /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, ExtMachInst _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, ExtMachInst _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 new 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(ExtMachInst _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..47d166255
--- /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 new 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 e64a95957..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/request.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..0cf31cb50 100644
--- a/arch/alpha/isa_traits.hh
+++ b/arch/alpha/isa_traits.hh
@@ -29,81 +29,131 @@
#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 ExecContext;
class FastCPU;
class FullCPU;
class Checkpoint;
#define TARGET_ALPHA
-template <class ISA> class StaticInst;
-template <class ISA> class StaticInstPtr;
+class StaticInst;
+class StaticInstPtr;
namespace EV5 {
int DTB_ASN_ASN(uint64_t reg);
int ITB_ASN_ASN(uint64_t reg);
}
-class AlphaISA
+#if !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
+
+
+
+namespace AlphaISA
{
- public:
typedef uint32_t MachInst;
- typedef uint64_t Addr;
+ typedef uint64_t ExtMachInst;
typedef uint8_t RegIndex;
- enum {
- MemoryEnd = 0xffffffffffffffffULL,
-
- NumIntRegs = 32,
- NumFloatRegs = 32,
- NumMiscRegs = 32,
-
- MaxRegsOfAnyType = 32,
- // Static instruction parameters
- MaxInstSrcRegs = 3,
- MaxInstDestRegs = 2,
-
- // semantically meaningful register indices
- ZeroReg = 31, // architecturally meaningful
- // the rest of these depend on the ABI
- StackPointerReg = 30,
- GlobalPointerReg = 29,
- ProcedureValueReg = 27,
- ReturnAddressReg = 26,
- ReturnValueReg = 0,
- FramePointerReg = 15,
- ArgumentReg0 = 16,
- ArgumentReg1 = 17,
- ArgumentReg2 = 18,
- ArgumentReg3 = 19,
- ArgumentReg4 = 20,
- ArgumentReg5 = 21,
-
- LogVMPageSize = 13, // 8K bytes
- VMPageSize = (1 << LogVMPageSize),
-
- BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned
-
- WordBytes = 4,
- HalfwordBytes = 2,
- ByteBytes = 1,
- DepNA = 0,
- };
+ const int NumIntArchRegs = 32;
+ const int NumPALShadowRegs = 8;
+ const int NumFloatArchRegs = 32;
+ // @todo: Figure out what this number really should be.
+ const int NumMiscArchRegs = 32;
+
+ // Static instruction parameters
+ const int MaxInstSrcRegs = 3;
+ const int MaxInstDestRegs = 2;
+
+ // semantically meaningful register indices
+ const int ZeroReg = 31; // architecturally meaningful
+ // the rest of these depend on the ABI
+ const int StackPointerReg = 30;
+ const int GlobalPointerReg = 29;
+ const int ProcedureValueReg = 27;
+ const int ReturnAddressReg = 26;
+ const int ReturnValueReg = 0;
+ const int FramePointerReg = 15;
+ const int ArgumentReg0 = 16;
+ const int ArgumentReg1 = 17;
+ const int ArgumentReg2 = 18;
+ const int ArgumentReg3 = 19;
+ const int ArgumentReg4 = 20;
+ const int ArgumentReg5 = 21;
+ const int SyscallNumReg = ReturnValueReg;
+ const int SyscallPseudoReturnReg = ArgumentReg4;
+ const int SyscallSuccessReg = 19;
+
+
+
+ const int LogVMPageSize = 13; // 8K bytes
+ const int VMPageSize = (1 << LogVMPageSize);
+
+ const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
+
+ const int WordBytes = 4;
+ const int HalfwordBytes = 2;
+ const int ByteBytes = 1;
+
+
+ const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
+ const int NumFloatRegs = NumFloatArchRegs;
+ const int NumMiscRegs = NumMiscArchRegs;
// These enumerate all the registers for dependence tracking.
enum DependenceTags {
// 0..31 are the integer regs 0..31
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
- FP_Base_DepTag = 32,
- Ctrl_Base_DepTag = 64,
- Fpcr_DepTag = 64, // floating point control register
- Uniq_DepTag = 65,
- IPR_Base_DepTag = 66
+ FP_Base_DepTag = 40,
+ Ctrl_Base_DepTag = 72,
+ Fpcr_DepTag = 72, // floating point control register
+ Uniq_DepTag = 73,
+ Lock_Flag_DepTag = 74,
+ Lock_Addr_DepTag = 75,
+ IPR_Base_DepTag = 76
};
typedef uint64_t IntReg;
@@ -120,40 +170,68 @@ class AlphaISA
double d[NumFloatRegs]; // double-precision floating point view
} FloatRegFile;
+extern const Addr PageShift;
+extern const Addr PageBytes;
+extern const Addr PageMask;
+extern const Addr PageOffset;
+
+// redirected register map, really only used for the full system case.
+extern const int reg_redir[NumIntRegs];
+
+#if FULL_SYSTEM
+
+ typedef uint64_t InternalProcReg;
+
+#include "arch/alpha/isa_fullsys_traits.hh"
+
+#else
+ const int NumInternalProcRegs = 0;
+#endif
+
// control register file contents
typedef uint64_t MiscReg;
- typedef struct {
+ class MiscRegFile {
+ protected:
uint64_t fpcr; // floating point condition codes
uint64_t uniq; // process-unique register
bool lock_flag; // lock flag for LL/SC
Addr lock_addr; // lock address for LL/SC
- } MiscRegFile;
-static const Addr PageShift = 13;
-static const Addr PageBytes = ULL(1) << PageShift;
-static const Addr PageMask = ~(PageBytes - 1);
-static const Addr PageOffset = PageBytes - 1;
+ public:
+ MiscReg readReg(int misc_reg);
+
+ //These functions should be removed once the simplescalar cpu model
+ //has been replaced.
+ int getInstAsid();
+ int getDataAsid();
+
+ MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc);
+
+ Fault setReg(int misc_reg, const MiscReg &val);
+
+ Fault setRegWithEffect(int misc_reg, const MiscReg &val,
+ ExecContext *xc);
+
+ void copyMiscRegs(ExecContext *xc);
#if FULL_SYSTEM
+ protected:
+ InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
- typedef uint64_t InternalProcReg;
+ private:
+ MiscReg readIpr(int idx, Fault &fault, ExecContext *xc);
-#include "arch/alpha/isa_fullsys_traits.hh"
+ Fault setIpr(int idx, uint64_t val, ExecContext *xc);
-#else
- enum {
- NumInternalProcRegs = 0
- };
+ void copyIprs(ExecContext *xc);
#endif
-
- enum {
- TotalNumRegs =
- NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
+ friend class RegFile;
};
- enum {
- TotalDataRegs = NumIntRegs + NumFloatRegs
- };
+ const int TotalNumRegs = NumIntRegs + NumFloatRegs +
+ NumMiscRegs + NumInternalProcRegs;
+
+ const int TotalDataRegs = NumIntRegs + NumFloatRegs;
typedef union {
IntReg intreg;
@@ -167,23 +245,26 @@ static const Addr PageOffset = PageBytes - 1;
MiscRegFile miscRegs; // control register file
Addr pc; // program counter
Addr npc; // next-cycle program counter
+ Addr nnpc;
+
#if FULL_SYSTEM
- IntReg palregs[NumIntRegs]; // PAL shadow registers
- InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
int intrflag; // interrupt flag
- bool pal_shadow; // using pal_shadow registers
- inline int instAsid() { return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
- inline int dataAsid() { return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
+ inline int instAsid()
+ { return EV5::ITB_ASN_ASN(miscRegs.ipr[IPR_ITB_ASN]); }
+ inline int dataAsid()
+ { return EV5::DTB_ASN_ASN(miscRegs.ipr[IPR_DTB_ASN]); }
#endif // FULL_SYSTEM
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
- static StaticInstPtr<AlphaISA> decodeInst(MachInst);
+ static inline ExtMachInst makeExtMI(MachInst inst, const uint64_t &pc);
+
+ StaticInstPtr decodeInst(ExtMachInst);
// return a no-op instruction... used for instruction fetch faults
- static const MachInst NoopMachInst;
+ extern const ExtMachInst NoopMachInst;
enum annotes {
ANNOTE_NONE = 0,
@@ -238,10 +319,10 @@ static const Addr PageOffset = PageBytes - 1;
// Machine operations
- static void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
+ void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
int regnum);
- static void restoreMachineReg(RegFile &regs, const AnyReg &reg,
+ void restoreMachineReg(RegFile &regs, const AnyReg &reg,
int regnum);
#if 0
@@ -259,82 +340,41 @@ static const Addr PageOffset = PageBytes - 1;
* @param xc The execution context.
*/
template <class XC>
- static void zeroRegisters(XC *xc);
-};
-
-
-typedef AlphaISA TheISA;
-
-typedef TheISA::MachInst MachInst;
-typedef TheISA::Addr Addr;
-typedef TheISA::RegIndex RegIndex;
-typedef TheISA::IntReg IntReg;
-typedef TheISA::IntRegFile IntRegFile;
-typedef TheISA::FloatReg FloatReg;
-typedef TheISA::FloatRegFile FloatRegFile;
-typedef TheISA::MiscReg MiscReg;
-typedef TheISA::MiscRegFile MiscRegFile;
-typedef TheISA::AnyReg AnyReg;
-typedef TheISA::RegFile RegFile;
-
-const int NumIntRegs = TheISA::NumIntRegs;
-const int NumFloatRegs = TheISA::NumFloatRegs;
-const int NumMiscRegs = TheISA::NumMiscRegs;
-const int TotalNumRegs = TheISA::TotalNumRegs;
-const int VMPageSize = TheISA::VMPageSize;
-const int LogVMPageSize = TheISA::LogVMPageSize;
-const int ZeroReg = TheISA::ZeroReg;
-const int StackPointerReg = TheISA::StackPointerReg;
-const int GlobalPointerReg = TheISA::GlobalPointerReg;
-const int ReturnAddressReg = TheISA::ReturnAddressReg;
-const int ReturnValueReg = TheISA::ReturnValueReg;
-const int ArgumentReg0 = TheISA::ArgumentReg0;
-const int ArgumentReg1 = TheISA::ArgumentReg1;
-const int ArgumentReg2 = TheISA::ArgumentReg2;
-const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
-const int MaxAddr = (Addr)-1;
-
-#if !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;
+ void zeroRegisters(XC *xc);
+
+ const Addr MaxAddr = (Addr)-1;
+
+ static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ if (return_value.successful()) {
+ // no error
+ regs->intRegFile[SyscallSuccessReg] = 0;
+ regs->intRegFile[ReturnValueReg] = return_value.value();
+ } else {
+ // got an error, return details
+ regs->intRegFile[SyscallSuccessReg] = (IntReg) -1;
+ regs->intRegFile[ReturnValueReg] = -return_value.value();
+ }
+ }
};
+static inline AlphaISA::ExtMachInst
+AlphaISA::makeExtMI(AlphaISA::MachInst inst, const uint64_t &pc) {
+#if FULL_SYSTEM
+ AlphaISA::ExtMachInst ext_inst = inst;
+ if (pc && 0x1)
+ return ext_inst|=(static_cast<AlphaISA::ExtMachInst>(pc & 0x1) << 32);
+ else
+ return ext_inst;
+#else
+ return AlphaISA::ExtMachInst(inst);
#endif
-
+}
#if FULL_SYSTEM
-typedef TheISA::InternalProcReg InternalProcReg;
-const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
-const int NumInterruptLevels = TheISA::NumInterruptLevels;
#include "arch/alpha/ev5.hh"
#endif
diff --git a/kern/linux/aligned.hh b/arch/alpha/linux/aligned.hh
index 18d1b43c0..cabecb283 100644
--- a/kern/linux/aligned.hh
+++ b/arch/alpha/linux/aligned.hh
@@ -26,15 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __KERN_LINUX_ALIGNED_HH__
-#define __KERN_LINUX_ALIGNED_HH__
+#ifndef __ARCH_ALPHA_LINUX_ALIGNED_HH__
+#define __ARCH_ALPHA_LINUX_ALIGNED_HH__
/* GCC 3.3.X has a bug in which attributes+typedefs don't work. 3.2.X is fine
* as in 3.4.X, but the bug is marked will not fix in 3.3.X so here is
* the work around.
*/
-#if __GNUC__ == 3 && __GNUC_MINOR__ != 3
+#if (__GNUC__ == 3 && __GNUC_MINOR__ != 3) || __GNUC__ > 3
typedef uint64_t uint64_ta __attribute__ ((aligned (8))) ;
typedef int64_t int64_ta __attribute__ ((aligned (8))) ;
typedef Addr Addr_a __attribute__ ((aligned (8))) ;
@@ -44,4 +44,4 @@ typedef Addr Addr_a __attribute__ ((aligned (8))) ;
#define Addr_a Addr __attribute__ ((aligned (8)))
#endif /* __GNUC__ __GNUC_MINOR__ */
-#endif /* __KERN_LINUX_ALIGNED_HH__ */
+#endif /* __ARCH_ALPHA_LINUX_ALIGNED_HH__ */
diff --git a/kern/linux/hwrpb.hh b/arch/alpha/linux/hwrpb.hh
index 4c8ac32e8..869ce026b 100644
--- a/kern/linux/hwrpb.hh
+++ b/arch/alpha/linux/hwrpb.hh
@@ -22,10 +22,10 @@
* SOFTWARE.
*/
-#ifndef __KERN_LINUX_HWRPB_HH__
-#define __KERN_LINUX_HWRPB_HH__
+#ifndef __ARCH_ALPHA_LINUX_HWRPB_HH__
+#define __ARCH_ALPHA_LINUX_HWRPB_HH__
-#include "kern/linux/aligned.hh"
+#include "arch/alpha/linux/aligned.hh"
namespace Linux {
struct pcb_struct {
@@ -39,4 +39,4 @@ namespace Linux {
uint64_ta res1, res2;
};
}
-#endif // __KERN_LINUX_HWRPB_HH__
+#endif // __ARCH_ALPHA_LINUX_HWRPB_HH__
diff --git a/arch/alpha/linux/process.cc b/arch/alpha/linux/process.cc
new file mode 100644
index 000000000..1c911bc50
--- /dev/null
+++ b/arch/alpha/linux/process.cc
@@ -0,0 +1,589 @@
+/*
+ * 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/alpha/linux/process.hh"
+#include "arch/alpha/isa_traits.hh"
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/linux.hh"
+#include "mem/functional/functional.hh"
+
+#include "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "Linux");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "2.4.20");
+ strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+ strcpy(name->machine, "alpha");
+
+ name.copyOut(xc->getMemPtr());
+ return 0;
+}
+
+/// Target osf_getsysyinfo() handler. Even though this call is
+/// borrowed from Tru64, the subcases that get used appear to be
+/// different in practice from those used by Tru64 processes.
+static SyscallReturn
+osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ // unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case 45: { // GSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+ // I don't think this exactly matches the HW FPCR
+ *fpcr = 0;
+ fpcr.copyOut(xc->getMemPtr());
+ return 0;
+ }
+
+ default:
+ cerr << "osf_getsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
+
+ return 1;
+}
+
+/// Target osf_setsysinfo() handler.
+static SyscallReturn
+osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ // unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case 14: { // SSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+ // I don't think this exactly matches the HW FPCR
+ fpcr.copyIn(xc->getMemPtr());
+ DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
+ " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
+ return 0;
+ }
+
+ default:
+ cerr << "osf_setsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
+
+ return 1;
+}
+
+
+SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
+ /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc),
+ /* 1 */ SyscallDesc("exit", exitFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", readFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("osf_old_open", unimplementedFunc),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("osf_wait4", unimplementedFunc),
+ /* 8 */ SyscallDesc("osf_old_creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("osf_execve", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>),
+ /* 16 */ SyscallDesc("chown", chownFunc),
+ /* 17 */ SyscallDesc("brk", obreakFunc),
+ /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", lseekFunc),
+ /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
+ /* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("umount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", setuidFunc),
+ /* 24 */ SyscallDesc("getxuid", getuidPseudoFunc),
+ /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+ /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc),
+ /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc),
+ /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc),
+ /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc),
+ /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc),
+ /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc),
+ /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc),
+ /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", pipePseudoFunc),
+ /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
+ /* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
+ /* 45 */ SyscallDesc("open", openFunc<Linux>),
+ /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
+ /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc),
+ /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
+ /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc),
+ /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>),
+ /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc),
+ /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc),
+ /* 57 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 58 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 59 */ SyscallDesc("execve", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc),
+ /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
+ /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
+ /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc),
+ /* 66 */ SyscallDesc("vfork", unimplementedFunc),
+ /* 67 */ SyscallDesc("stat", statFunc<Linux>),
+ /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>),
+ /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc),
+ /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>),
+ /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc),
+ /* 73 */ SyscallDesc("munmap", munmapFunc),
+ /* 74 */ SyscallDesc("mprotect", ignoreFunc),
+ /* 75 */ SyscallDesc("madvise", unimplementedFunc),
+ /* 76 */ SyscallDesc("vhangup", unimplementedFunc),
+ /* 77 */ SyscallDesc("osf_kmodcall", unimplementedFunc),
+ /* 78 */ SyscallDesc("osf_mincore", unimplementedFunc),
+ /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 81 */ SyscallDesc("osf_old_getpgrp", unimplementedFunc),
+ /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
+ /* 83 */ SyscallDesc("osf_setitimer", unimplementedFunc),
+ /* 84 */ SyscallDesc("osf_old_wait", unimplementedFunc),
+ /* 85 */ SyscallDesc("osf_table", unimplementedFunc),
+ /* 86 */ SyscallDesc("osf_getitimer", unimplementedFunc),
+ /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
+ /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
+ /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
+ /* 90 */ SyscallDesc("dup2", unimplementedFunc),
+ /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>),
+ /* 92 */ SyscallDesc("fcntl", fcntlFunc),
+ /* 93 */ SyscallDesc("osf_select", unimplementedFunc),
+ /* 94 */ SyscallDesc("poll", unimplementedFunc),
+ /* 95 */ SyscallDesc("fsync", unimplementedFunc),
+ /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
+ /* 97 */ SyscallDesc("socket", unimplementedFunc),
+ /* 98 */ SyscallDesc("connect", unimplementedFunc),
+ /* 99 */ SyscallDesc("accept", unimplementedFunc),
+ /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
+ /* 101 */ SyscallDesc("send", unimplementedFunc),
+ /* 102 */ SyscallDesc("recv", unimplementedFunc),
+ /* 103 */ SyscallDesc("sigreturn", unimplementedFunc),
+ /* 104 */ SyscallDesc("bind", unimplementedFunc),
+ /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
+ /* 106 */ SyscallDesc("listen", unimplementedFunc),
+ /* 107 */ SyscallDesc("osf_plock", unimplementedFunc),
+ /* 108 */ SyscallDesc("osf_old_sigvec", unimplementedFunc),
+ /* 109 */ SyscallDesc("osf_old_sigblock", unimplementedFunc),
+ /* 110 */ SyscallDesc("osf_old_sigsetmask", unimplementedFunc),
+ /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 112 */ SyscallDesc("osf_sigstack", ignoreFunc),
+ /* 113 */ SyscallDesc("recvmsg", unimplementedFunc),
+ /* 114 */ SyscallDesc("sendmsg", unimplementedFunc),
+ /* 115 */ SyscallDesc("osf_old_vtrace", unimplementedFunc),
+ /* 116 */ SyscallDesc("osf_gettimeofday", unimplementedFunc),
+ /* 117 */ SyscallDesc("osf_getrusage", unimplementedFunc),
+ /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
+ /* 120 */ SyscallDesc("readv", unimplementedFunc),
+ /* 121 */ SyscallDesc("writev", writevFunc<Linux>),
+ /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc),
+ /* 123 */ SyscallDesc("fchown", fchownFunc),
+ /* 124 */ SyscallDesc("fchmod", fchmodFunc<Linux>),
+ /* 125 */ SyscallDesc("recvfrom", unimplementedFunc),
+ /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 127 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 128 */ SyscallDesc("rename", renameFunc),
+ /* 129 */ SyscallDesc("truncate", unimplementedFunc),
+ /* 130 */ SyscallDesc("ftruncate", unimplementedFunc),
+ /* 131 */ SyscallDesc("flock", unimplementedFunc),
+ /* 132 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 133 */ SyscallDesc("sendto", unimplementedFunc),
+ /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
+ /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
+ /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc),
+ /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc),
+ /* 140 */ SyscallDesc("osf_adjtime", unimplementedFunc),
+ /* 141 */ SyscallDesc("getpeername", unimplementedFunc),
+ /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc),
+ /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc),
+ /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>),
+ /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
+ /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc),
+ /* 147 */ SyscallDesc("setsid", unimplementedFunc),
+ /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
+ /* 149 */ SyscallDesc("osf_oldquota", unimplementedFunc),
+ /* 150 */ SyscallDesc("getsockname", unimplementedFunc),
+ /* 151 */ SyscallDesc("osf_pread", unimplementedFunc),
+ /* 152 */ SyscallDesc("osf_pwrite", unimplementedFunc),
+ /* 153 */ SyscallDesc("osf_pid_block", unimplementedFunc),
+ /* 154 */ SyscallDesc("osf_pid_unblock", unimplementedFunc),
+ /* 155 */ SyscallDesc("osf_signal_urti", unimplementedFunc),
+ /* 156 */ SyscallDesc("sigaction", ignoreFunc),
+ /* 157 */ SyscallDesc("osf_sigwaitprim", unimplementedFunc),
+ /* 158 */ SyscallDesc("osf_nfssvc", unimplementedFunc),
+ /* 159 */ SyscallDesc("osf_getdirentries", unimplementedFunc),
+ /* 160 */ SyscallDesc("osf_statfs", unimplementedFunc),
+ /* 161 */ SyscallDesc("osf_fstatfs", unimplementedFunc),
+ /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
+ /* 163 */ SyscallDesc("osf_async_daemon", unimplementedFunc),
+ /* 164 */ SyscallDesc("osf_getfh", unimplementedFunc),
+ /* 165 */ SyscallDesc("osf_getdomainname", unimplementedFunc),
+ /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
+ /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
+ /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
+ /* 169 */ SyscallDesc("osf_exportfs", unimplementedFunc),
+ /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
+ /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
+ /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
+ /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
+ /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
+ /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
+ /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
+ /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
+ /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
+ /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
+ /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
+ /* 181 */ SyscallDesc("osf_alt_plock", unimplementedFunc),
+ /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+ /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
+ /* 184 */ SyscallDesc("osf_getmnt", unimplementedFunc),
+ /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
+ /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
+ /* 187 */ SyscallDesc("osf_alt_sigpending", unimplementedFunc),
+ /* 188 */ SyscallDesc("osf_alt_setsid", unimplementedFunc),
+ /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
+ /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
+ /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
+ /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
+ /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
+ /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
+ /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
+ /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
+ /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
+ /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
+ /* 199 */ SyscallDesc("osf_swapon", unimplementedFunc),
+ /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
+ /* 201 */ SyscallDesc("msgget", unimplementedFunc),
+ /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
+ /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
+ /* 204 */ SyscallDesc("semctl", unimplementedFunc),
+ /* 205 */ SyscallDesc("semget", unimplementedFunc),
+ /* 206 */ SyscallDesc("semop", unimplementedFunc),
+ /* 207 */ SyscallDesc("osf_utsname", unimplementedFunc),
+ /* 208 */ SyscallDesc("lchown", unimplementedFunc),
+ /* 209 */ SyscallDesc("osf_shmat", unimplementedFunc),
+ /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
+ /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
+ /* 212 */ SyscallDesc("shmget", unimplementedFunc),
+ /* 213 */ SyscallDesc("osf_mvalid", unimplementedFunc),
+ /* 214 */ SyscallDesc("osf_getaddressconf", unimplementedFunc),
+ /* 215 */ SyscallDesc("osf_msleep", unimplementedFunc),
+ /* 216 */ SyscallDesc("osf_mwakeup", unimplementedFunc),
+ /* 217 */ SyscallDesc("msync", unimplementedFunc),
+ /* 218 */ SyscallDesc("osf_signal", unimplementedFunc),
+ /* 219 */ SyscallDesc("osf_utc_gettime", unimplementedFunc),
+ /* 220 */ SyscallDesc("osf_utc_adjtime", unimplementedFunc),
+ /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
+ /* 222 */ SyscallDesc("osf_security", unimplementedFunc),
+ /* 223 */ SyscallDesc("osf_kloadcall", unimplementedFunc),
+ /* 224 */ SyscallDesc("unknown #224", unimplementedFunc),
+ /* 225 */ SyscallDesc("unknown #225", unimplementedFunc),
+ /* 226 */ SyscallDesc("unknown #226", unimplementedFunc),
+ /* 227 */ SyscallDesc("unknown #227", unimplementedFunc),
+ /* 228 */ SyscallDesc("unknown #228", unimplementedFunc),
+ /* 229 */ SyscallDesc("unknown #229", unimplementedFunc),
+ /* 230 */ SyscallDesc("unknown #230", unimplementedFunc),
+ /* 231 */ SyscallDesc("unknown #231", unimplementedFunc),
+ /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
+ /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
+ /* 234 */ SyscallDesc("getsid", unimplementedFunc),
+ /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
+ /* 236 */ SyscallDesc("osf_waitid", unimplementedFunc),
+ /* 237 */ SyscallDesc("osf_priocntlset", unimplementedFunc),
+ /* 238 */ SyscallDesc("osf_sigsendset", unimplementedFunc),
+ /* 239 */ SyscallDesc("osf_set_speculative", unimplementedFunc),
+ /* 240 */ SyscallDesc("osf_msfs_syscall", unimplementedFunc),
+ /* 241 */ SyscallDesc("osf_sysinfo", unimplementedFunc),
+ /* 242 */ SyscallDesc("osf_uadmin", unimplementedFunc),
+ /* 243 */ SyscallDesc("osf_fuser", unimplementedFunc),
+ /* 244 */ SyscallDesc("osf_proplist_syscall", unimplementedFunc),
+ /* 245 */ SyscallDesc("osf_ntp_adjtime", unimplementedFunc),
+ /* 246 */ SyscallDesc("osf_ntp_gettime", unimplementedFunc),
+ /* 247 */ SyscallDesc("osf_pathconf", unimplementedFunc),
+ /* 248 */ SyscallDesc("osf_fpathconf", unimplementedFunc),
+ /* 249 */ SyscallDesc("unknown #249", unimplementedFunc),
+ /* 250 */ SyscallDesc("osf_uswitch", unimplementedFunc),
+ /* 251 */ SyscallDesc("osf_usleep_thread", unimplementedFunc),
+ /* 252 */ SyscallDesc("osf_audcntl", unimplementedFunc),
+ /* 253 */ SyscallDesc("osf_audgen", unimplementedFunc),
+ /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 255 */ SyscallDesc("osf_subsys_info", unimplementedFunc),
+ /* 256 */ SyscallDesc("osf_getsysinfo", osf_getsysinfoFunc),
+ /* 257 */ SyscallDesc("osf_setsysinfo", osf_setsysinfoFunc),
+ /* 258 */ SyscallDesc("osf_afs_syscall", unimplementedFunc),
+ /* 259 */ SyscallDesc("osf_swapctl", unimplementedFunc),
+ /* 260 */ SyscallDesc("osf_memcntl", unimplementedFunc),
+ /* 261 */ SyscallDesc("osf_fdatasync", unimplementedFunc),
+ /* 262 */ SyscallDesc("unknown #262", unimplementedFunc),
+ /* 263 */ SyscallDesc("unknown #263", unimplementedFunc),
+ /* 264 */ SyscallDesc("unknown #264", unimplementedFunc),
+ /* 265 */ SyscallDesc("unknown #265", unimplementedFunc),
+ /* 266 */ SyscallDesc("unknown #266", unimplementedFunc),
+ /* 267 */ SyscallDesc("unknown #267", unimplementedFunc),
+ /* 268 */ SyscallDesc("unknown #268", unimplementedFunc),
+ /* 269 */ SyscallDesc("unknown #269", unimplementedFunc),
+ /* 270 */ SyscallDesc("unknown #270", unimplementedFunc),
+ /* 271 */ SyscallDesc("unknown #271", unimplementedFunc),
+ /* 272 */ SyscallDesc("unknown #272", unimplementedFunc),
+ /* 273 */ SyscallDesc("unknown #273", unimplementedFunc),
+ /* 274 */ SyscallDesc("unknown #274", unimplementedFunc),
+ /* 275 */ SyscallDesc("unknown #275", unimplementedFunc),
+ /* 276 */ SyscallDesc("unknown #276", unimplementedFunc),
+ /* 277 */ SyscallDesc("unknown #277", unimplementedFunc),
+ /* 278 */ SyscallDesc("unknown #278", unimplementedFunc),
+ /* 279 */ SyscallDesc("unknown #279", unimplementedFunc),
+ /* 280 */ SyscallDesc("unknown #280", unimplementedFunc),
+ /* 281 */ SyscallDesc("unknown #281", unimplementedFunc),
+ /* 282 */ SyscallDesc("unknown #282", unimplementedFunc),
+ /* 283 */ SyscallDesc("unknown #283", unimplementedFunc),
+ /* 284 */ SyscallDesc("unknown #284", unimplementedFunc),
+ /* 285 */ SyscallDesc("unknown #285", unimplementedFunc),
+ /* 286 */ SyscallDesc("unknown #286", unimplementedFunc),
+ /* 287 */ SyscallDesc("unknown #287", unimplementedFunc),
+ /* 288 */ SyscallDesc("unknown #288", unimplementedFunc),
+ /* 289 */ SyscallDesc("unknown #289", unimplementedFunc),
+ /* 290 */ SyscallDesc("unknown #290", unimplementedFunc),
+ /* 291 */ SyscallDesc("unknown #291", unimplementedFunc),
+ /* 292 */ SyscallDesc("unknown #292", unimplementedFunc),
+ /* 293 */ SyscallDesc("unknown #293", unimplementedFunc),
+ /* 294 */ SyscallDesc("unknown #294", unimplementedFunc),
+ /* 295 */ SyscallDesc("unknown #295", unimplementedFunc),
+ /* 296 */ SyscallDesc("unknown #296", unimplementedFunc),
+ /* 297 */ SyscallDesc("unknown #297", unimplementedFunc),
+ /* 298 */ SyscallDesc("unknown #298", unimplementedFunc),
+ /* 299 */ SyscallDesc("unknown #299", unimplementedFunc),
+/*
+ * Linux-specific system calls begin at 300
+ */
+ /* 300 */ SyscallDesc("bdflush", unimplementedFunc),
+ /* 301 */ SyscallDesc("sethae", unimplementedFunc),
+ /* 302 */ SyscallDesc("mount", unimplementedFunc),
+ /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc),
+ /* 304 */ SyscallDesc("swapoff", unimplementedFunc),
+ /* 305 */ SyscallDesc("getdents", unimplementedFunc),
+ /* 306 */ SyscallDesc("create_module", unimplementedFunc),
+ /* 307 */ SyscallDesc("init_module", unimplementedFunc),
+ /* 308 */ SyscallDesc("delete_module", unimplementedFunc),
+ /* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
+ /* 310 */ SyscallDesc("syslog", unimplementedFunc),
+ /* 311 */ SyscallDesc("reboot", unimplementedFunc),
+ /* 312 */ SyscallDesc("clone", unimplementedFunc),
+ /* 313 */ SyscallDesc("uselib", unimplementedFunc),
+ /* 314 */ SyscallDesc("mlock", unimplementedFunc),
+ /* 315 */ SyscallDesc("munlock", unimplementedFunc),
+ /* 316 */ SyscallDesc("mlockall", unimplementedFunc),
+ /* 317 */ SyscallDesc("munlockall", unimplementedFunc),
+ /* 318 */ SyscallDesc("sysinfo", unimplementedFunc),
+ /* 319 */ SyscallDesc("_sysctl", unimplementedFunc),
+ /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc),
+ /* 321 */ SyscallDesc("oldumount", unimplementedFunc),
+ /* 322 */ SyscallDesc("swapon", unimplementedFunc),
+ /* 323 */ SyscallDesc("times", ignoreFunc),
+ /* 324 */ SyscallDesc("personality", unimplementedFunc),
+ /* 325 */ SyscallDesc("setfsuid", unimplementedFunc),
+ /* 326 */ SyscallDesc("setfsgid", unimplementedFunc),
+ /* 327 */ SyscallDesc("ustat", unimplementedFunc),
+ /* 328 */ SyscallDesc("statfs", unimplementedFunc),
+ /* 329 */ SyscallDesc("fstatfs", unimplementedFunc),
+ /* 330 */ SyscallDesc("sched_setparam", unimplementedFunc),
+ /* 331 */ SyscallDesc("sched_getparam", unimplementedFunc),
+ /* 332 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
+ /* 333 */ SyscallDesc("sched_getscheduler", unimplementedFunc),
+ /* 334 */ SyscallDesc("sched_yield", unimplementedFunc),
+ /* 335 */ SyscallDesc("sched_get_priority_max", unimplementedFunc),
+ /* 336 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
+ /* 337 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
+ /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc),
+ /* 339 */ SyscallDesc("uname", unameFunc),
+ /* 340 */ SyscallDesc("nanosleep", unimplementedFunc),
+ /* 341 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc),
+ /* 343 */ SyscallDesc("setresuid", unimplementedFunc),
+ /* 344 */ SyscallDesc("getresuid", unimplementedFunc),
+ /* 345 */ SyscallDesc("pciconfig_read", unimplementedFunc),
+ /* 346 */ SyscallDesc("pciconfig_write", unimplementedFunc),
+ /* 347 */ SyscallDesc("query_module", unimplementedFunc),
+ /* 348 */ SyscallDesc("prctl", unimplementedFunc),
+ /* 349 */ SyscallDesc("pread", unimplementedFunc),
+ /* 350 */ SyscallDesc("pwrite", unimplementedFunc),
+ /* 351 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
+ /* 352 */ SyscallDesc("rt_sigaction", ignoreFunc),
+ /* 353 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
+ /* 354 */ SyscallDesc("rt_sigpending", unimplementedFunc),
+ /* 355 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
+ /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
+ /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
+ /* 358 */ SyscallDesc("select", unimplementedFunc),
+ /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>),
+ /* 360 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 361 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 362 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 363 */ SyscallDesc("utimes", utimesFunc<Linux>),
+ /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>),
+ /* 365 */ SyscallDesc("wait4", unimplementedFunc),
+ /* 366 */ SyscallDesc("adjtimex", unimplementedFunc),
+ /* 367 */ SyscallDesc("getcwd", unimplementedFunc),
+ /* 368 */ SyscallDesc("capget", unimplementedFunc),
+ /* 369 */ SyscallDesc("capset", unimplementedFunc),
+ /* 370 */ SyscallDesc("sendfile", unimplementedFunc),
+ /* 371 */ SyscallDesc("setresgid", unimplementedFunc),
+ /* 372 */ SyscallDesc("getresgid", unimplementedFunc),
+ /* 373 */ SyscallDesc("dipc", unimplementedFunc),
+ /* 374 */ SyscallDesc("pivot_root", unimplementedFunc),
+ /* 375 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc),
+ /* 377 */ SyscallDesc("getdents64", unimplementedFunc),
+ /* 378 */ SyscallDesc("gettid", unimplementedFunc),
+ /* 379 */ SyscallDesc("readahead", unimplementedFunc),
+ /* 380 */ SyscallDesc("security", unimplementedFunc),
+ /* 381 */ SyscallDesc("tkill", unimplementedFunc),
+ /* 382 */ SyscallDesc("setxattr", unimplementedFunc),
+ /* 383 */ SyscallDesc("lsetxattr", unimplementedFunc),
+ /* 384 */ SyscallDesc("fsetxattr", unimplementedFunc),
+ /* 385 */ SyscallDesc("getxattr", unimplementedFunc),
+ /* 386 */ SyscallDesc("lgetxattr", unimplementedFunc),
+ /* 387 */ SyscallDesc("fgetxattr", unimplementedFunc),
+ /* 388 */ SyscallDesc("listxattr", unimplementedFunc),
+ /* 389 */ SyscallDesc("llistxattr", unimplementedFunc),
+ /* 390 */ SyscallDesc("flistxattr", unimplementedFunc),
+ /* 391 */ SyscallDesc("removexattr", unimplementedFunc),
+ /* 392 */ SyscallDesc("lremovexattr", unimplementedFunc),
+ /* 393 */ SyscallDesc("fremovexattr", unimplementedFunc),
+ /* 394 */ SyscallDesc("futex", unimplementedFunc),
+ /* 395 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
+ /* 396 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
+ /* 397 */ SyscallDesc("tuxcall", unimplementedFunc),
+ /* 398 */ SyscallDesc("io_setup", unimplementedFunc),
+ /* 399 */ SyscallDesc("io_destroy", unimplementedFunc),
+ /* 400 */ SyscallDesc("io_getevents", unimplementedFunc),
+ /* 401 */ SyscallDesc("io_submit", unimplementedFunc),
+ /* 402 */ SyscallDesc("io_cancel", unimplementedFunc),
+ /* 403 */ SyscallDesc("unknown #403", unimplementedFunc),
+ /* 404 */ SyscallDesc("unknown #404", unimplementedFunc),
+ /* 405 */ SyscallDesc("exit_group", exitFunc), // exit all threads...
+ /* 406 */ SyscallDesc("lookup_dcookie", unimplementedFunc),
+ /* 407 */ SyscallDesc("sys_epoll_create", unimplementedFunc),
+ /* 408 */ SyscallDesc("sys_epoll_ctl", unimplementedFunc),
+ /* 409 */ SyscallDesc("sys_epoll_wait", unimplementedFunc),
+ /* 410 */ SyscallDesc("remap_file_pages", unimplementedFunc),
+ /* 411 */ SyscallDesc("set_tid_address", unimplementedFunc),
+ /* 412 */ SyscallDesc("restart_syscall", unimplementedFunc),
+ /* 413 */ SyscallDesc("fadvise64", unimplementedFunc),
+ /* 414 */ SyscallDesc("timer_create", unimplementedFunc),
+ /* 415 */ SyscallDesc("timer_settime", unimplementedFunc),
+ /* 416 */ SyscallDesc("timer_gettime", unimplementedFunc),
+ /* 417 */ SyscallDesc("timer_getoverrun", unimplementedFunc),
+ /* 418 */ SyscallDesc("timer_delete", unimplementedFunc),
+ /* 419 */ SyscallDesc("clock_settime", unimplementedFunc),
+ /* 420 */ SyscallDesc("clock_gettime", unimplementedFunc),
+ /* 421 */ SyscallDesc("clock_getres", unimplementedFunc),
+ /* 422 */ SyscallDesc("clock_nanosleep", unimplementedFunc),
+ /* 423 */ SyscallDesc("semtimedop", unimplementedFunc),
+ /* 424 */ SyscallDesc("tgkill", unimplementedFunc),
+ /* 425 */ SyscallDesc("stat64", unimplementedFunc),
+ /* 426 */ SyscallDesc("lstat64", lstat64Func<Linux>),
+ /* 427 */ SyscallDesc("fstat64", fstat64Func<Linux>),
+ /* 428 */ SyscallDesc("vserver", unimplementedFunc),
+ /* 429 */ SyscallDesc("mbind", unimplementedFunc),
+ /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc),
+ /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc),
+ /* 432 */ SyscallDesc("mq_open", unimplementedFunc),
+ /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc),
+ /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc),
+ /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc),
+ /* 436 */ SyscallDesc("mq_notify", unimplementedFunc),
+ /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc),
+ /* 438 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 439 */ SyscallDesc("add_key", unimplementedFunc),
+ /* 440 */ SyscallDesc("request_key", unimplementedFunc),
+ /* 441 */ SyscallDesc("keyctl", unimplementedFunc)
+};
+
+AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
+ ObjectFile *objFile,
+ int stdin_fd,
+ int stdout_fd,
+ int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp)
+ : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
+{
+ init_regs->intRegFile[0] = 0;
+}
+
+
+
+SyscallDesc*
+AlphaLinuxProcess::getDesc(int callnum)
+{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
+}
diff --git a/arch/alpha/alpha_linux_process.hh b/arch/alpha/linux/process.hh
index 6a4f31e5b..2cabc3f76 100644
--- a/arch/alpha/alpha_linux_process.hh
+++ b/arch/alpha/linux/process.hh
@@ -44,8 +44,15 @@ class AlphaLinuxProcess : public LiveProcess
std::vector<std::string> &argv,
std::vector<std::string> &envp);
- /// Syscall emulation function.
- virtual void syscall(ExecContext *xc);
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
};
diff --git a/kern/linux/linux_system.cc b/arch/alpha/linux/system.cc
index 1144b9bdd..f9275d15e 100644
--- a/kern/linux/linux_system.cc
+++ b/arch/alpha/linux/system.cc
@@ -35,23 +35,28 @@
* up boot time.
*/
+#include "arch/arguments.hh"
+#include "arch/vtophys.hh"
+#include "arch/alpha/linux/system.hh"
+#include "arch/alpha/linux/threadinfo.hh"
+#include "arch/alpha/system.hh"
#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh"
#include "cpu/base.hh"
-#include "kern/linux/linux_system.hh"
-#include "kern/linux/linux_threadinfo.hh"
+#include "dev/platform.hh"
#include "kern/linux/printk.hh"
+#include "kern/linux/events.hh"
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
-#include "dev/platform.hh"
-#include "targetarch/arguments.hh"
-#include "targetarch/vtophys.hh"
+#include "sim/byteswap.hh"
using namespace std;
+using namespace AlphaISA;
+using namespace Linux;
-LinuxSystem::LinuxSystem(Params *p)
- : System(p)
+LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
+ : AlphaSystem(p)
{
Addr addr = 0;
Addr paddr = 0;
@@ -71,7 +76,7 @@ LinuxSystem::LinuxSystem(Params *p)
paddr = vtophys(physmem, CommandLine());
char *commandline = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
if (commandline)
- strncpy(commandline, params->boot_osflags.c_str(), CommandLineSize);
+ strncpy(commandline, params()->boot_osflags.c_str(), CommandLineSize);
/**
* find the address of the est_cycle_freq variable and insert it
@@ -100,7 +105,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");
@@ -144,7 +149,7 @@ LinuxSystem::LinuxSystem(Params *p)
printThreadEvent = NULL;
}
- if (params->bin_int) {
+ if (params()->bin_int) {
intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
if (!intStartEvent)
panic("could not find symbol: sys_int_21\n");
@@ -163,7 +168,7 @@ LinuxSystem::LinuxSystem(Params *p)
}
}
-LinuxSystem::~LinuxSystem()
+LinuxAlphaSystem::~LinuxAlphaSystem()
{
#ifndef NDEBUG
delete kernelPanicEvent;
@@ -181,7 +186,7 @@ LinuxSystem::~LinuxSystem()
void
-LinuxSystem::setDelayLoop(ExecContext *xc)
+LinuxAlphaSystem::setDelayLoop(ExecContext *xc)
{
Addr addr = 0;
if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
@@ -190,38 +195,24 @@ LinuxSystem::setDelayLoop(ExecContext *xc)
uint8_t *loops_per_jiffy =
physmem->dma_addr(paddr, sizeof(uint32_t));
- Tick cpuFreq = xc->cpu->frequency();
+ Tick cpuFreq = xc->getCpuPtr()->frequency();
Tick intrFreq = platform->intrFrequency();
*(uint32_t *)loops_per_jiffy =
(uint32_t)((cpuFreq / intrFreq) * 0.9988);
}
}
+
void
-LinuxSystem::SkipDelayLoopEvent::process(ExecContext *xc)
+LinuxAlphaSystem::SkipDelayLoopEvent::process(ExecContext *xc)
{
SkipFuncEvent::process(xc);
// calculate and set loops_per_jiffy
- ((LinuxSystem *)xc->system)->setDelayLoop(xc);
-}
-
-void
-LinuxSystem::DebugPrintkEvent::process(ExecContext *xc)
-{
- if (DTRACE(DebugPrintf)) {
- if (!raw) {
- StringWrap name(xc->system->name() + ".dprintk");
- DPRINTFN("");
- }
-
- AlphaArguments args(xc);
- Printk(args);
- SkipFuncEvent::process(xc);
- }
+ ((LinuxAlphaSystem *)xc->getSystemPtr())->setDelayLoop(xc);
}
void
-LinuxSystem::PrintThreadInfo::process(ExecContext *xc)
+LinuxAlphaSystem::PrintThreadInfo::process(ExecContext *xc)
{
Linux::ThreadInfo ti(xc);
@@ -230,7 +221,7 @@ LinuxSystem::PrintThreadInfo::process(ExecContext *xc)
}
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<MemoryController *> memctrl;
@@ -251,9 +242,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
VectorParam<string> binned_fns;
Param<bool> bin_int;
-END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
+END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
-BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
+BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(memctrl, "memory controller"),
@@ -271,11 +262,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
INIT_PARAM(binned_fns, "functions to be broken down and binned"),
INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
-END_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
+END_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
-CREATE_SIM_OBJECT(LinuxSystem)
+CREATE_SIM_OBJECT(LinuxAlphaSystem)
{
- System::Params *p = new System::Params;
+ AlphaSystem::Params *p = new AlphaSystem::Params;
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->memctrl = memctrl;
@@ -291,8 +282,8 @@ CREATE_SIM_OBJECT(LinuxSystem)
p->bin = bin;
p->binned_fns = binned_fns;
p->bin_int = bin_int;
- return new LinuxSystem(p);
+ return new LinuxAlphaSystem(p);
}
-REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
+REGISTER_SIM_OBJECT("LinuxAlphaSystem", LinuxAlphaSystem)
diff --git a/kern/linux/linux_system.hh b/arch/alpha/linux/system.hh
index f883bef93..035e2a427 100644
--- a/kern/linux/linux_system.hh
+++ b/arch/alpha/linux/system.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,21 +26,27 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __KERN_LINUX_LINUX_SYSTEM_HH__
-#define __KERN_LINUX_LINUX_SYSTEM_HH__
+#ifndef __ARCH_ALPHA_LINUX_SYSTEM_HH__
+#define __ARCH_ALPHA_LINUX_SYSTEM_HH__
class ExecContext;
class BreakPCEvent;
class IdleStartEvent;
-class PrintThreadInfo;
+
+#include "arch/alpha/system.hh"
+#include "kern/linux/events.hh"
+
+using namespace AlphaISA;
+using namespace Linux;
+using namespace std;
/**
* This class contains linux specific system code (Loading, Events, Binning).
* It points to objects that are the system binaries to load and patches them
* appropriately to work in simulator.
*/
-class LinuxSystem : public System
+class LinuxAlphaSystem : public AlphaSystem
{
private:
class SkipDelayLoopEvent : public SkipFuncEvent
@@ -51,18 +57,6 @@ class LinuxSystem : public System
virtual void process(ExecContext *xc);
};
- class DebugPrintkEvent : public SkipFuncEvent
- {
- private:
- bool raw;
-
- public:
- DebugPrintkEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- bool r = false)
- : SkipFuncEvent(q, desc, addr), raw(r) {}
- virtual void process(ExecContext *xc);
- };
-
class PrintThreadInfo : public PCEvent
{
public:
@@ -71,6 +65,7 @@ class LinuxSystem : public System
virtual void process(ExecContext *xc);
};
+
/**
* Addresses defining where the kernel bootloader places various
* elements. Details found in include/asm-alpha/system.h
@@ -142,10 +137,10 @@ class LinuxSystem : public System
IdleStartEvent *idleStartEvent;
public:
- LinuxSystem(Params *p);
- ~LinuxSystem();
+ LinuxAlphaSystem(Params *p);
+ ~LinuxAlphaSystem();
void setDelayLoop(ExecContext *xc);
};
-#endif // __KERN_LINUX_LINUX_SYSTEM_HH__
+#endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__
diff --git a/kern/linux/thread_info.hh b/arch/alpha/linux/thread_info.hh
index cf24ef939..88791b00d 100644
--- a/kern/linux/thread_info.hh
+++ b/arch/alpha/linux/thread_info.hh
@@ -26,10 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __KERN_LINUX_THREAD_INFO_H__
-#define __KERN_LINUX_THREAD_INFO_H__
+#ifndef __ARCH_ALPHA_LINUX_THREAD_INFO_H__
+#define __ARCH_ALPHA_LINUX_THREAD_INFO_H__
-#include "kern/linux/hwrpb.hh"
+#include "arch/alpha/linux/hwrpb.hh"
namespace Linux {
struct thread_info {
@@ -38,4 +38,4 @@ namespace Linux {
};
}
-#endif // __KERN_LINUX_THREAD_INFO_H__
+#endif // __ARCH_ALPHA_LINUX_THREAD_INFO_H__
diff --git a/kern/linux/linux_threadinfo.hh b/arch/alpha/linux/threadinfo.hh
index 0c60b9f5c..8f03c9314 100644
--- a/kern/linux/linux_threadinfo.hh
+++ b/arch/alpha/linux/threadinfo.hh
@@ -26,12 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __KERN_LINUX_LINUX_TREADNIFO_HH__
-#define __KERN_LINUX_LINUX_TREADNIFO_HH__
+#ifndef __ARCH_ALPHA_LINUX_LINUX_TREADNIFO_HH__
+#define __ARCH_ALPHA_LINUX_LINUX_TREADNIFO_HH__
-#include "kern/linux/thread_info.hh"
+#include "arch/alpha/linux/thread_info.hh"
+#include "cpu/exec_context.hh"
#include "kern/linux/sched.hh"
-#include "targetarch/vptr.hh"
+#include "sim/vptr.hh"
namespace Linux {
@@ -53,7 +54,7 @@ class ThreadInfo
* thread_info struct. So we can get the address by masking off
* the lower 14 bits.
*/
- current = xc->regs.intRegFile[StackPointerReg] & ~0x3fff;
+ current = xc->readIntReg(TheISA::StackPointerReg) & ~0x3fff;
return VPtr<thread_info>(xc, current);
}
@@ -85,4 +86,4 @@ class ThreadInfo
/* namespace Linux */ }
-#endif // __KERN_LINUX_LINUX_THREADINFO_HH__
+#endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__
diff --git a/arch/alpha/process.cc b/arch/alpha/process.cc
new file mode 100644
index 000000000..b2dbe7ad1
--- /dev/null
+++ b/arch/alpha/process.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#include "arch/alpha/process.hh"
+
+namespace AlphaISA
+{
+
+LiveProcess *
+createProcess(const std::string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
+{
+ LiveProcess * process = NULL;
+ if (objFile->getArch() != ObjectFile::Alpha)
+ fatal("Object file does not match architecture.");
+ switch (objFile->getOpSys()) {
+ case ObjectFile::Tru64:
+ process = new AlphaTru64Process(nm, objFile,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ case ObjectFile::Linux:
+ process = new AlphaLinuxProcess(nm, objFile,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+ return process;
+}
+
+} // namespace AlphaISA
diff --git a/arch/alpha/process.hh b/arch/alpha/process.hh
new file mode 100644
index 000000000..4a2a4212e
--- /dev/null
+++ b/arch/alpha/process.hh
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef __ALPHA_PROCESS_HH__
+#define __ALPHA_PROCESS_HH__
+
+#include <string>
+
+#include "arch/alpha/linux/process.hh"
+#include "arch/alpha/tru64/process.hh"
+#include "base/loader/object_file.hh"
+
+namespace AlphaISA
+{
+
+LiveProcess *
+createProcess(const std::string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp);
+
+} // namespace AlphaISA
+
+#endif // __ALPHA_PROCESS_HH__
diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc
index 5a8df3d35..26656ab5c 100644
--- a/arch/alpha/stacktrace.cc
+++ b/arch/alpha/stacktrace.cc
@@ -35,31 +35,33 @@
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
+#include "sim/system.hh"
using namespace std;
+using namespace AlphaISA;
ProcessInfo::ProcessInfo(ExecContext *_xc)
: xc(_xc)
{
Addr addr = 0;
- if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
panic("thread info not compiled into kernel\n");
thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
panic("thread info not compiled into kernel\n");
task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
panic("thread info not compiled into kernel\n");
task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
panic("thread info not compiled into kernel\n");
pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n");
name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
}
@@ -108,7 +110,7 @@ StackTrace::StackTrace()
{
}
-StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst)
+StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst)
: xc(0), stack(64)
{
trace(_xc, inst);
@@ -123,10 +125,11 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
{
xc = _xc;
- bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0;
+ bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
- Addr pc = xc->regs.npc;
- bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd;
+ Addr pc = xc->readNextPC();
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
if (usermode) {
stack.push_back(user);
@@ -138,8 +141,8 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
return;
}
- SymbolTable *symtab = xc->system->kernelSymtab;
- Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg];
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
+ Addr ksp = xc->readIntReg(TheISA::StackPointerReg);
Addr bottom = ksp & ~0x3fff;
Addr addr;
@@ -148,7 +151,7 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
panic("could not find address %#x", pc);
stack.push_back(addr);
- pc = xc->regs.pc;
+ pc = xc->readPC();
}
Addr ra;
@@ -180,8 +183,8 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
return;
}
- bool kernel = xc->system->kernelStart <= pc &&
- pc <= xc->system->kernelEnd;
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
if (!kernel)
return;
@@ -195,22 +198,22 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
bool
StackTrace::isEntry(Addr addr)
{
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp12))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp7))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp11))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp21))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp9))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp2))
return true;
return false;
@@ -322,8 +325,8 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
void
StackTrace::dump()
{
- StringWrap name(xc->cpu->name());
- SymbolTable *symtab = xc->system->kernelSymtab;
+ StringWrap name(xc->getCpuPtr()->name());
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
DPRINTFN("------ Stack ------\n");
diff --git a/arch/alpha/stacktrace.hh b/arch/alpha/stacktrace.hh
index 244e574b6..1d8d97a79 100644
--- a/arch/alpha/stacktrace.hh
+++ b/arch/alpha/stacktrace.hh
@@ -56,6 +56,8 @@ class ProcessInfo
class StackTrace
{
+ protected:
+ typedef TheISA::MachInst MachInst;
private:
ExecContext *xc;
std::vector<Addr> stack;
@@ -70,7 +72,7 @@ class StackTrace
public:
StackTrace();
- StackTrace(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ StackTrace(ExecContext *xc, StaticInstPtr inst);
~StackTrace();
void clear()
@@ -80,7 +82,7 @@ class StackTrace
}
bool valid() const { return xc != NULL; }
- bool trace(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ bool trace(ExecContext *xc, StaticInstPtr inst);
public:
const std::vector<Addr> &getstack() const { return stack; }
@@ -102,7 +104,7 @@ class StackTrace
};
inline bool
-StackTrace::trace(ExecContext *xc, StaticInstPtr<TheISA> inst)
+StackTrace::trace(ExecContext *xc, StaticInstPtr inst)
{
if (!inst->isCall() && !inst->isReturn())
return false;
diff --git a/arch/alpha/system.cc b/arch/alpha/system.cc
new file mode 100644
index 000000000..25543da57
--- /dev/null
+++ b/arch/alpha/system.cc
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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/alpha/system.hh"
+#include "arch/vtophys.hh"
+#include "base/remote_gdb.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "mem/functional/memory_control.hh"
+#include "mem/functional/physical.hh"
+#include "sim/byteswap.hh"
+#include "sim/builder.hh"
+
+
+using namespace LittleEndianGuest;
+
+AlphaSystem::AlphaSystem(Params *p)
+ : System(p)
+{
+ consoleSymtab = new SymbolTable;
+ palSymtab = new SymbolTable;
+
+
+ /**
+ * Load the pal, and console code into memory
+ */
+ // Load Console Code
+ console = createObjectFile(params()->console_path);
+ if (console == NULL)
+ fatal("Could not load console file %s", params()->console_path);
+
+ // Load pal file
+ pal = createObjectFile(params()->palcode);
+ if (pal == NULL)
+ fatal("Could not load PALcode file %s", params()->palcode);
+
+
+ // Load program sections into memory
+ pal->loadSections(physmem, true);
+ console->loadSections(physmem, true);
+
+ // load symbols
+ if (!console->loadGlobalSymbols(consoleSymtab))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!console->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ Addr addr = 0;
+#ifndef NDEBUG
+ consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
+#endif
+
+ /**
+ * Copy the osflags (kernel arguments) into the consoles
+ * memory. (Presently Linux does not use the console service
+ * routine to get these command line arguments, but Tru64 and
+ * others do.)
+ */
+ if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
+
+ if (osflags)
+ strcpy(osflags, params()->boot_osflags.c_str());
+ }
+
+ /**
+ * Set the hardware reset parameter block system type and revision
+ * information to Tsunami.
+ */
+ if (consoleSymtab->findAddress("m5_rpb", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
+
+ if (!hwrpb)
+ panic("could not translate hwrpb addr\n");
+
+ *(uint64_t*)(hwrpb+0x50) = htog(params()->system_type);
+ *(uint64_t*)(hwrpb+0x58) = htog(params()->system_rev);
+ } else
+ panic("could not find hwrpb\n");
+
+}
+
+AlphaSystem::~AlphaSystem()
+{
+ delete consoleSymtab;
+ delete console;
+ delete pal;
+#ifdef DEBUG
+ delete consolePanicEvent;
+#endif
+}
+
+/**
+ * This function fixes up addresses that are used to match PCs for
+ * hooking simulator events on to target function executions.
+ *
+ * Alpha binaries may have multiple global offset table (GOT)
+ * sections. A function that uses the GOT starts with a
+ * two-instruction prolog which sets the global pointer (gp == r29) to
+ * the appropriate GOT section. The proper gp value is calculated
+ * based on the function address, which must be passed by the caller
+ * in the procedure value register (pv aka t12 == r27). This sequence
+ * looks like the following:
+ *
+ * opcode Ra Rb offset
+ * ldah gp,X(pv) 09 29 27 X
+ * lda gp,Y(gp) 08 29 29 Y
+ *
+ * for some constant offsets X and Y. The catch is that the linker
+ * (or maybe even the compiler, I'm not sure) may recognize that the
+ * caller and callee are using the same GOT section, making this
+ * prolog redundant, and modify the call target to skip these
+ * instructions. If we check for execution of the first instruction
+ * of a function (the one the symbol points to) to detect when to skip
+ * it, we'll miss all these modified calls. It might work to
+ * unconditionally check for the third instruction, but not all
+ * functions have this prolog, and there's some chance that those
+ * first two instructions could have undesired consequences. So we do
+ * the Right Thing and pattern-match the first two instructions of the
+ * function to decide where to patch.
+ *
+ * Eventually this code should be moved into an ISA-specific file.
+ */
+Addr
+AlphaSystem::fixFuncEventAddr(Addr addr)
+{
+ // mask for just the opcode, Ra, and Rb fields (not the offset)
+ const uint32_t inst_mask = 0xffff0000;
+ // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
+ const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
+ // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
+ const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
+ // instruction size
+ const int sz = sizeof(uint32_t);
+
+ Addr paddr = vtophys(physmem, addr);
+ uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz);
+ uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz);
+
+ if ((i1 & inst_mask) == gp_ldah_pattern &&
+ (i2 & inst_mask) == gp_lda_pattern) {
+ Addr new_addr = addr + 2*sz;
+ DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
+ return new_addr;
+ } else {
+ return addr;
+ }
+}
+
+
+void
+AlphaSystem::setAlphaAccess(Addr access)
+{
+ Addr addr = 0;
+ if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ uint64_t *m5AlphaAccess =
+ (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t));
+
+ if (!m5AlphaAccess)
+ panic("could not translate m5AlphaAccess addr\n");
+
+ *m5AlphaAccess = htog(EV5::Phys2K0Seg(access));
+ } else
+ panic("could not find m5AlphaAccess\n");
+}
+
+bool
+AlphaSystem::breakpoint()
+{
+ return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+}
+
+void
+AlphaSystem::serialize(std::ostream &os)
+{
+ System::serialize(os);
+ consoleSymtab->serialize("console_symtab", os);
+ palSymtab->serialize("pal_symtab", os);
+}
+
+
+void
+AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
+{
+ System::unserialize(cp,section);
+ consoleSymtab->unserialize("console_symtab", cp, section);
+ palSymtab->unserialize("pal_symtab", cp, section);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<MemoryController *> memctrl;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<std::string> kernel;
+ Param<std::string> console;
+ Param<std::string> pal;
+
+ Param<std::string> boot_osflags;
+ Param<std::string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<std::string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(memctrl, "memory controller"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+CREATE_SIM_OBJECT(AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->memctrl = memctrl;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem)
+
+
diff --git a/arch/alpha/system.hh b/arch/alpha/system.hh
new file mode 100644
index 000000000..fe1307ac3
--- /dev/null
+++ b/arch/alpha/system.hh
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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_ALPHA_SYSTEM_HH__
+#define __ARCH_ALPHA_SYSTEM_HH__
+
+#include <string>
+#include <vector>
+
+#include "sim/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/pc_event.hh"
+#include "kern/system_events.hh"
+#include "sim/sim_object.hh"
+
+class AlphaSystem : public System
+{
+ public:
+ struct Params : public System::Params
+ {
+ std::string console_path;
+ std::string palcode;
+ std::string boot_osflags;
+ uint64_t system_type;
+ uint64_t system_rev;
+ };
+
+ AlphaSystem(Params *p);
+
+ ~AlphaSystem();
+
+ virtual bool breakpoint();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ /**
+ * Set the m5AlphaAccess pointer in the console
+ */
+ void setAlphaAccess(Addr access);
+
+ /** console symbol table */
+ SymbolTable *consoleSymtab;
+
+ /** pal symbol table */
+ SymbolTable *palSymtab;
+
+ /** Object pointer for the console code */
+ ObjectFile *console;
+
+ /** Object pointer for the PAL code */
+ ObjectFile *pal;
+
+#ifndef NDEBUG
+ /** Event to halt the simulator if the console calls panic() */
+ BreakPCEvent *consolePanicEvent;
+#endif
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ /** Add a function-based event to PALcode. */
+ template <class T>
+ T *AlphaSystem::addPalFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(palSymtab, lbl);
+ }
+
+ /** Add a function-based event to the console code. */
+ template <class T>
+ T *AlphaSystem::addConsoleFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(consoleSymtab, lbl);
+ }
+
+ virtual Addr fixFuncEventAddr(Addr addr);
+
+};
+
+#endif
+
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/tlb.cc
index 8dda4d9c4..e30a8e595 100644
--- a/arch/alpha/alpha_memory.cc
+++ b/arch/alpha/tlb.cc
@@ -30,7 +30,7 @@
#include <string>
#include <vector>
-#include "arch/alpha/alpha_memory.hh"
+#include "arch/alpha/tlb.hh"
#include "base/inifile.hh"
#include "base/str.hh"
#include "base/trace.hh"
@@ -293,12 +293,11 @@ AlphaITB::regStats()
void
AlphaITB::fault(Addr pc, ExecContext *xc) const
{
- uint64_t *ipr = xc->regs.ipr;
-
if (!xc->misspeculating()) {
- ipr[AlphaISA::IPR_ITB_TAG] = pc;
- ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
- ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3);
+ xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
+ xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
+ (AlphaISA::VAddr(pc).vpn() << 3));
}
}
@@ -306,13 +305,13 @@ AlphaITB::fault(Addr pc, ExecContext *xc) const
Fault
AlphaITB::translate(MemReqPtr &req) const
{
- InternalProcReg *ipr = req->xc->regs.ipr;
+ ExecContext *xc = req->xc;
if (AlphaISA::PcPAL(req->vaddr)) {
// 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,24 +321,24 @@ AlphaITB::translate(MemReqPtr &req) const
if (!validVirtualAddress(req->vaddr)) {
fault(req->vaddr, req->xc);
acv++;
- return ITB_Acv_Fault;
+ return new ItbAcvFault;
}
// VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
// VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
#if ALPHA_TLASER
- if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
+ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
VAddrSpaceEV5(req->vaddr) == 2) {
#else
if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
#endif
// only valid in kernel mode
- if (ICM_CM(ipr[AlphaISA::IPR_ICM]) !=
+ if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
AlphaISA::mode_kernel) {
fault(req->vaddr, req->xc);
acv++;
- return ITB_Acv_Fault;
+ return new ItbAcvFault;
}
req->paddr = req->vaddr & PAddrImplMask;
@@ -354,24 +353,26 @@ AlphaITB::translate(MemReqPtr &req) const
} else {
// not a physical address: need to look up pte
+ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN));
AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ asn);
if (!pte) {
fault(req->vaddr, req->xc);
misses++;
- return ITB_Fault_Fault;
+ return new ItbPageFault;
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
(AlphaISA::VAddr(req->vaddr).offset() & ~3);
// check permissions for this access
- if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
+ if (!(pte->xre &
+ (1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
// instruction access fault
fault(req->vaddr, req->xc);
acv++;
- return ITB_Acv_Fault;
+ return new ItbAcvFault;
}
hits++;
@@ -380,11 +381,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 genMachineCheckFault();
checkCacheability(req);
- return No_Fault;
+ return NoFault;
}
///////////////////////////////////////////////////////////////////////
@@ -469,7 +470,6 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
{
ExecContext *xc = req->xc;
AlphaISA::VAddr vaddr = req->vaddr;
- uint64_t *ipr = xc->regs.ipr;
// Set fault address and flags. Even though we're modeling an
// EV5, we use the EV6 technique of not latching fault registers
@@ -479,29 +479,28 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
if (!xc->misspeculating()
&& !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
// set VA register with faulting address
- ipr[AlphaISA::IPR_VA] = req->vaddr;
+ xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr);
// set MM_STAT register flags
- ipr[AlphaISA::IPR_MM_STAT] =
+ xc->setMiscReg(AlphaISA::IPR_MM_STAT,
(((Opcode(xc->getInst()) & 0x3f) << 11)
| ((Ra(xc->getInst()) & 0x1f) << 6)
- | (flags & 0x3f));
+ | (flags & 0x3f)));
// set VA_FORM register with faulting formatted address
- ipr[AlphaISA::IPR_VA_FORM] =
- ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3);
+ xc->setMiscReg(AlphaISA::IPR_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
}
}
Fault
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
- RegFile *regs = &req->xc->regs;
- Addr pc = regs->pc;
- InternalProcReg *ipr = regs->ipr;
+ ExecContext *xc = req->xc;
+ Addr pc = xc->readPC();
AlphaISA::mode_type mode =
- (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
+ (AlphaISA::mode_type)DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM));
/**
@@ -511,12 +510,13 @@ 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 genAlignmentFault();
}
if (pc & 0x1) {
mode = (req->flags & ALTMODE) ?
- (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
+ (AlphaISA::mode_type)ALT_MODE_AM(
+ xc->readMiscReg(AlphaISA::IPR_ALT_MODE))
: AlphaISA::mode_kernel;
}
@@ -530,24 +530,24 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
MM_STAT_ACV_MASK);
if (write) { write_acv++; } else { read_acv++; }
- return DTB_Fault_Fault;
+ return new DtbPageFault;
}
// Check for "superpage" mapping
#if ALPHA_TLASER
- if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
+ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
VAddrSpaceEV5(req->vaddr) == 2) {
#else
if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
#endif
// only valid in kernel mode
- if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
+ if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
AlphaISA::mode_kernel) {
fault(req, ((write ? MM_STAT_WR_MASK : 0) |
MM_STAT_ACV_MASK));
if (write) { write_acv++; } else { read_acv++; }
- return DTB_Acv_Fault;
+ return new DtbAcvFault;
}
req->paddr = req->vaddr & PAddrImplMask;
@@ -566,16 +566,20 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
else
read_accesses++;
+ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN));
+
// not a physical address: need to look up pte
AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ asn);
if (!pte) {
// page fault
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)(new PDtbMissFault) :
+ (Fault)(new NDtbMissFault);
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
@@ -588,25 +592,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 new DtbPageFault;
}
if (pte->fonw) {
fault(req, MM_STAT_WR_MASK |
MM_STAT_FONW_MASK);
write_acv++;
- return DTB_Fault_Fault;
+ return new 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 new DtbAcvFault;
}
if (pte->fonr) {
fault(req, MM_STAT_FONR_MASK);
read_acv++;
- return DTB_Fault_Fault;
+ return new DtbPageFault;
}
}
}
@@ -619,11 +623,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 genMachineCheckFault();
checkCacheability(req);
- return No_Fault;
+ return NoFault;
}
AlphaISA::PTE &
diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/tlb.hh
index 788923434..de955fa46 100644
--- a/arch/alpha/alpha_memory.hh
+++ b/arch/alpha/tlb.hh
@@ -32,6 +32,7 @@
#include <map>
#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/faults.hh"
#include "base/statistics.hh"
#include "mem/mem_req.hh"
#include "sim/sim_object.hh"
diff --git a/arch/alpha/tru64/process.cc b/arch/alpha/tru64/process.cc
new file mode 100644
index 000000000..c3a203587
--- /dev/null
+++ b/arch/alpha/tru64/process.cc
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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/alpha/isa_traits.hh"
+#include "arch/alpha/tru64/process.hh"
+#include "cpu/exec_context.hh"
+#include "kern/tru64/tru64.hh"
+#include "mem/functional/functional.hh"
+#include "sim/fake_syscall.hh"
+#include "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "OSF1");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "V5.1");
+ strcpy(name->version, "732");
+ strcpy(name->machine, "alpha");
+
+ name.copyOut(xc->getMemPtr());
+ return 0;
+}
+
+/// Target getsysyinfo() handler.
+static SyscallReturn
+getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case Tru64::GSI_MAX_CPU: {
+ TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
+ *max_cpu = htog((uint32_t)process->numCpus());
+ max_cpu.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_CPUS_IN_BOX: {
+ TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
+ *cpus_in_box = htog((uint32_t)process->numCpus());
+ cpus_in_box.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_PHYSMEM: {
+ TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
+ *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
+ physmem.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_CPU_INFO: {
+ TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
+
+ infop->current_cpu = htog(0);
+ infop->cpus_in_box = htog(process->numCpus());
+ infop->cpu_type = htog(57);
+ infop->ncpus = htog(process->numCpus());
+ uint64_t cpumask = (1 << process->numCpus()) - 1;
+ infop->cpus_present = infop->cpus_running = htog(cpumask);
+ infop->cpu_binding = htog(0);
+ infop->cpu_ex_binding = htog(0);
+ infop->mhz = htog(667);
+
+ infop.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_PROC_TYPE: {
+ TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
+ *proc_type = htog((uint64_t)11);
+ proc_type.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_PLATFORM_NAME: {
+ BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+ strncpy((char *)bufArg.bufferPtr(),
+ "COMPAQ Professional Workstation XP1000",
+ nbytes);
+ bufArg.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_CLK_TCK: {
+ TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
+ *clk_hz = htog((uint64_t)1024);
+ clk_hz.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ default:
+ warn("getsysinfo: unknown op %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+/// Target setsysyinfo() handler.
+static SyscallReturn
+setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+
+ switch (op) {
+ case Tru64::SSI_IEEE_FP_CONTROL:
+ warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
+ xc->getSyscallArg(1));
+ break;
+
+ default:
+ warn("setsysinfo: unknown op %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+
+SyscallDesc AlphaTru64Process::syscallDescs[] = {
+ /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc,
+ SyscallDesc::SuppressReturnValue),
+ /* 1 */ SyscallDesc("exit", exitFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", readFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("old_open", unimplementedFunc),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("wait4", unimplementedFunc),
+ /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("execv", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", unimplementedFunc),
+ /* 16 */ SyscallDesc("chown", unimplementedFunc),
+ /* 17 */ SyscallDesc("obreak", obreakFunc),
+ /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", lseekFunc),
+ /* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
+ /* 21 */ SyscallDesc("mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("unmount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", setuidFunc),
+ /* 24 */ SyscallDesc("getuid", getuidPseudoFunc),
+ /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+ /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
+ /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
+ /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
+ /* 30 */ SyscallDesc("accept", unimplementedFunc),
+ /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
+ /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("chflags", unimplementedFunc),
+ /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
+ /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+ /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
+ /* 44 */ SyscallDesc("profil", unimplementedFunc),
+ /* 45 */ SyscallDesc("open", openFunc<Tru64>),
+ /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
+ /* 47 */ SyscallDesc("getgid", getgidPseudoFunc),
+ /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
+ /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
+ /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
+ /* 55 */ SyscallDesc("reboot", unimplementedFunc),
+ /* 56 */ SyscallDesc("revoke", unimplementedFunc),
+ /* 57 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 58 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 59 */ SyscallDesc("execve", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
+ /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
+ /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
+ /* 65 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 66 */ SyscallDesc("vfork", unimplementedFunc),
+ /* 67 */ SyscallDesc("pre_F64_stat", statFunc<Tru64::PreF64>),
+ /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<Tru64::PreF64>),
+ /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
+ /* 70 */ SyscallDesc("sstk", unimplementedFunc),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
+ /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
+ /* 73 */ SyscallDesc("munmap", munmapFunc),
+ /* 74 */ SyscallDesc("mprotect", ignoreFunc),
+ /* 75 */ SyscallDesc("madvise", unimplementedFunc),
+ /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
+ /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
+ /* 78 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
+ /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
+ /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
+ /* 85 */ SyscallDesc("table", Tru64::tableFunc),
+ /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
+ /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
+ /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
+ /* 90 */ SyscallDesc("dup2", unimplementedFunc),
+ /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<Tru64::PreF64>),
+ /* 92 */ SyscallDesc("fcntl", fcntlFunc),
+ /* 93 */ SyscallDesc("select", unimplementedFunc),
+ /* 94 */ SyscallDesc("poll", unimplementedFunc),
+ /* 95 */ SyscallDesc("fsync", unimplementedFunc),
+ /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
+ /* 97 */ SyscallDesc("socket", unimplementedFunc),
+ /* 98 */ SyscallDesc("connect", unimplementedFunc),
+ /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
+ /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
+ /* 101 */ SyscallDesc("old_send", unimplementedFunc),
+ /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
+ /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc,
+ SyscallDesc::SuppressReturnValue),
+ /* 104 */ SyscallDesc("bind", unimplementedFunc),
+ /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
+ /* 106 */ SyscallDesc("listen", unimplementedFunc),
+ /* 107 */ SyscallDesc("plock", unimplementedFunc),
+ /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
+ /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
+ /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
+ /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 112 */ SyscallDesc("sigstack", ignoreFunc),
+ /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
+ /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
+ /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
+ /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>),
+ /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>),
+ /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
+ /* 120 */ SyscallDesc("readv", unimplementedFunc),
+ /* 121 */ SyscallDesc("writev", unimplementedFunc),
+ /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 123 */ SyscallDesc("fchown", unimplementedFunc),
+ /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
+ /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
+ /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 127 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 128 */ SyscallDesc("rename", renameFunc),
+ /* 129 */ SyscallDesc("truncate", truncateFunc),
+ /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
+ /* 131 */ SyscallDesc("flock", unimplementedFunc),
+ /* 132 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 133 */ SyscallDesc("sendto", unimplementedFunc),
+ /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
+ /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
+ /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 138 */ SyscallDesc("utimes", unimplementedFunc),
+ /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
+ /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
+ /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
+ /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
+ /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
+ /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
+ /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
+ /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
+ /* 147 */ SyscallDesc("setsid", unimplementedFunc),
+ /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
+ /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
+ /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
+ /* 151 */ SyscallDesc("pread", unimplementedFunc),
+ /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
+ /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
+ /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
+ /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
+ /* 156 */ SyscallDesc("sigaction", ignoreFunc),
+ /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
+ /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
+ /* 159 */ SyscallDesc("getdirentries", Tru64::getdirentriesFunc),
+ /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>),
+ /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>),
+ /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
+ /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
+ /* 164 */ SyscallDesc("getfh", unimplementedFunc),
+ /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
+ /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
+ /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
+ /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
+ /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
+ /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
+ /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
+ /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
+ /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
+ /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
+ /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
+ /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
+ /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
+ /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
+ /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
+ /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
+ /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
+ /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+ /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
+ /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
+ /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
+ /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
+ /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
+ /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
+ /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
+ /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
+ /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
+ /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
+ /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
+ /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
+ /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
+ /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
+ /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
+ /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
+ /* 199 */ SyscallDesc("swapon", unimplementedFunc),
+ /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
+ /* 201 */ SyscallDesc("msgget", unimplementedFunc),
+ /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
+ /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
+ /* 204 */ SyscallDesc("semctl", unimplementedFunc),
+ /* 205 */ SyscallDesc("semget", unimplementedFunc),
+ /* 206 */ SyscallDesc("semop", unimplementedFunc),
+ /* 207 */ SyscallDesc("uname", unameFunc),
+ /* 208 */ SyscallDesc("lchown", unimplementedFunc),
+ /* 209 */ SyscallDesc("shmat", unimplementedFunc),
+ /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
+ /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
+ /* 212 */ SyscallDesc("shmget", unimplementedFunc),
+ /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
+ /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
+ /* 215 */ SyscallDesc("msleep", unimplementedFunc),
+ /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
+ /* 217 */ SyscallDesc("msync", unimplementedFunc),
+ /* 218 */ SyscallDesc("signal", unimplementedFunc),
+ /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
+ /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
+ /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
+ /* 222 */ SyscallDesc("security", unimplementedFunc),
+ /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
+ /* 224 */ SyscallDesc("stat", statFunc<Tru64::F64>),
+ /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64::F64>),
+ /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64::F64>),
+ /* 227 */ SyscallDesc("statfs", statfsFunc<Tru64::F64>),
+ /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<Tru64::F64>),
+ /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
+ /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
+ /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
+ /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
+ /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
+ /* 234 */ SyscallDesc("getsid", unimplementedFunc),
+ /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
+ /* 236 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
+ /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
+ /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
+ /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
+ /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
+ /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
+ /* 243 */ SyscallDesc("fuser", unimplementedFunc),
+ /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
+ /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
+ /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
+ /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
+ /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
+ /* 249 */ SyscallDesc("sync2", unimplementedFunc),
+ /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
+ /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
+ /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
+ /* 253 */ SyscallDesc("audgen", unimplementedFunc),
+ /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
+ /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
+ /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc),
+ /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
+ /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
+ /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
+ /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
+ /* 262 */ SyscallDesc("oflock", unimplementedFunc),
+ /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
+ /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
+ /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
+ /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
+};
+
+
+
+SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
+ /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 1 */ SyscallDesc("m5_mutex_lock", Tru64::m5_mutex_lockFunc),
+ /* 2 */ SyscallDesc("m5_mutex_trylock", Tru64::m5_mutex_trylockFunc),
+ /* 3 */ SyscallDesc("m5_mutex_unlock", Tru64::m5_mutex_unlockFunc),
+ /* 4 */ SyscallDesc("m5_cond_signal", Tru64::m5_cond_signalFunc),
+ /* 5 */ SyscallDesc("m5_cond_broadcast", Tru64::m5_cond_broadcastFunc),
+ /* 6 */ SyscallDesc("m5_cond_wait", Tru64::m5_cond_waitFunc),
+ /* 7 */ SyscallDesc("m5_thread_exit", Tru64::m5_thread_exitFunc),
+ /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 10 */ SyscallDesc("task_self", unimplementedFunc),
+ /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
+ /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
+ /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
+ /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
+ /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
+ /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
+ /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 24 */ SyscallDesc("nxm_block", Tru64::nxm_blockFunc),
+ /* 25 */ SyscallDesc("nxm_unblock", Tru64::nxm_unblockFunc),
+ /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
+ /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
+ /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
+ /* 32 */ SyscallDesc("nxm_thread_create", Tru64::nxm_thread_createFunc),
+ /* 33 */ SyscallDesc("nxm_task_init", Tru64::nxm_task_initFunc),
+ /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc),
+ /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
+ /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
+ /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
+ /* 39 */ SyscallDesc("nxm_thread_block", Tru64::nxm_thread_blockFunc),
+ /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
+ /* 41 */ SyscallDesc("init_process", unimplementedFunc),
+ /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
+ /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
+ /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
+ /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
+ /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
+ /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc),
+ /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
+ /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
+ /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
+ /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
+ /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
+ /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 55 */ SyscallDesc("host_self", unimplementedFunc),
+ /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
+ /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc),
+ /* 60 */ SyscallDesc("swtch", unimplementedFunc),
+ /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
+ /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
+ /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
+ /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
+ /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
+ /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
+ /* 67 */ SyscallDesc("nxm_swtch_pri", Tru64::swtch_priFunc),
+ /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
+ /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
+ /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
+ /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
+ /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
+ /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
+ /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
+ /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
+ /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
+ /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
+ /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
+ /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
+ /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
+ /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
+};
+
+SyscallDesc*
+AlphaTru64Process::getDesc(int callnum)
+{
+ if (callnum < -Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs)
+ return NULL;
+
+ if (callnum < 0)
+ return &machSyscallDescs[-callnum];
+ else
+ return &syscallDescs[callnum];
+}
+
+
+AlphaTru64Process::AlphaTru64Process(const std::string &name,
+ ObjectFile *objFile,
+ int stdin_fd,
+ int stdout_fd,
+ int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp)
+ : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)),
+ Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc))
+{
+}
diff --git a/arch/alpha/alpha_tru64_process.hh b/arch/alpha/tru64/process.hh
index c28598700..84abd54bf 100644
--- a/arch/alpha/alpha_tru64_process.hh
+++ b/arch/alpha/tru64/process.hh
@@ -43,8 +43,16 @@ class AlphaTru64Process : public LiveProcess
std::vector<std::string> &argv,
std::vector<std::string> &envp);
- /// Syscall emulation function.
- virtual void syscall(ExecContext *xc);
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ /// Array of mach syscall descriptors, indexed by call number.
+ static SyscallDesc machSyscallDescs[];
+
+ const int Num_Syscall_Descs;
+ const int Num_Mach_Syscall_Descs;
+
+ virtual SyscallDesc* getDesc(int callnum);
};
diff --git a/kern/tru64/tru64_system.cc b/arch/alpha/tru64/system.cc
index f65293474..d09a0c85d 100644
--- a/kern/tru64/tru64_system.cc
+++ b/arch/alpha/tru64/system.cc
@@ -26,23 +26,23 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/tru64/system.hh"
+#include "arch/isa_traits.hh"
+#include "arch/vtophys.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "kern/tru64/tru64_events.hh"
-#include "kern/tru64/tru64_system.hh"
#include "kern/system_events.hh"
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
-#include "targetarch/isa_traits.hh"
-#include "targetarch/vtophys.hh"
using namespace std;
-Tru64System::Tru64System(Tru64System::Params *p)
- : System(p)
+Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
+ : AlphaSystem(p)
{
Addr addr = 0;
if (kernelSymtab->findAddress("enable_async_printf", addr)) {
@@ -77,7 +77,7 @@ Tru64System::Tru64System(Tru64System::Params *p)
#endif
}
-Tru64System::~Tru64System()
+Tru64AlphaSystem::~Tru64AlphaSystem()
{
#ifdef DEBUG
delete kernelPanicEvent;
@@ -93,7 +93,7 @@ Tru64System::~Tru64System()
#endif
}
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<MemoryController *> memctrl;
@@ -113,9 +113,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
Param<bool> bin;
VectorParam<string> binned_fns;
-END_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
+END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
-BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System)
+BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
INIT_PARAM(memctrl, "memory controller"),
@@ -132,11 +132,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System)
INIT_PARAM_DFLT(bin, "is this system to be binned", false),
INIT_PARAM(binned_fns, "functions to be broken down and binned")
-END_INIT_SIM_OBJECT_PARAMS(Tru64System)
+END_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
-CREATE_SIM_OBJECT(Tru64System)
+CREATE_SIM_OBJECT(Tru64AlphaSystem)
{
- System::Params *p = new System::Params;
+ AlphaSystem::Params *p = new AlphaSystem::Params;
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->memctrl = memctrl;
@@ -153,7 +153,7 @@ CREATE_SIM_OBJECT(Tru64System)
p->binned_fns = binned_fns;
p->bin_int = false;
- return new Tru64System(p);
+ return new Tru64AlphaSystem(p);
}
-REGISTER_SIM_OBJECT("Tru64System", Tru64System)
+REGISTER_SIM_OBJECT("Tru64AlphaSystem", Tru64AlphaSystem)
diff --git a/kern/tru64/tru64_system.hh b/arch/alpha/tru64/system.hh
index a9077e112..0e0cc1bc8 100644
--- a/kern/tru64/tru64_system.hh
+++ b/arch/alpha/tru64/system.hh
@@ -26,11 +26,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __KERN_TRU64_TRU64_SYSTEM_HH__
-#define __KERN_TRU64_TRU64_SYSTEM_HH__
+#ifndef __ARCH_ALPHA_TRU64_SYSTEM_HH__
+#define __ARCH_ALPHA_TRU64_SYSTEM_HH__
+#include "arch/alpha/system.hh"
+#include "arch/isa_traits.hh"
#include "sim/system.hh"
-#include "targetarch/isa_traits.hh"
class ExecContext;
@@ -39,10 +40,11 @@ class BadAddrEvent;
class SkipFuncEvent;
class PrintfEvent;
class DebugPrintfEvent;
+class DebugPrintfrEvent;
class DumpMbufEvent;
class AlphaArguments;
-class Tru64System : public System
+class Tru64AlphaSystem : public AlphaSystem
{
private:
#ifdef DEBUG
@@ -59,11 +61,11 @@ class Tru64System : public System
DumpMbufEvent *dumpMbufEvent;
public:
- Tru64System(Params *p);
- ~Tru64System();
+ Tru64AlphaSystem(Params *p);
+ ~Tru64AlphaSystem();
static void Printf(AlphaArguments args);
static void DumpMbuf(AlphaArguments args);
};
-#endif // __KERN_TRU64_TRU64_SYSTEM_HH__
+#endif // __ARCH_ALPHA_TRU64_SYSTEM_HH__
diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc
index 27014164c..40261426d 100644
--- a/arch/alpha/vtophys.cc
+++ b/arch/alpha/vtophys.cc
@@ -34,6 +34,7 @@
#include "mem/functional/physical.hh"
using namespace std;
+using namespace AlphaISA;
AlphaISA::PageTableEntry
kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
@@ -81,7 +82,7 @@ Addr
vtophys(ExecContext *xc, Addr addr)
{
AlphaISA::VAddr vaddr = addr;
- Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
+ Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20);
Addr paddr = 0;
//@todo Andrew couldn't remember why he commented some of this code
//so I put it back in. Perhaps something to do with gdb debugging?
@@ -94,7 +95,7 @@ vtophys(ExecContext *xc, Addr addr)
paddr = vaddr;
} else {
AlphaISA::PageTableEntry pte =
- kernel_pte_lookup(xc->physmem, ptbr, vaddr);
+ kernel_pte_lookup(xc->getPhysMemPtr(), ptbr, vaddr);
if (pte.valid())
paddr = pte.paddr() | vaddr.offset();
}
@@ -109,14 +110,14 @@ vtophys(ExecContext *xc, Addr addr)
uint8_t *
ptomem(ExecContext *xc, Addr paddr, size_t len)
{
- return xc->physmem->dma_addr(paddr, len);
+ return xc->getPhysMemPtr()->dma_addr(paddr, len);
}
uint8_t *
vtomem(ExecContext *xc, Addr vaddr, size_t len)
{
Addr paddr = vtophys(xc, vaddr);
- return xc->physmem->dma_addr(paddr, len);
+ return xc->getPhysMemPtr()->dma_addr(paddr, len);
}
void
@@ -130,7 +131,7 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
paddr = vtophys(xc, src);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)cplen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
memcpy(dst, dmaaddr, len);
@@ -143,7 +144,8 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
memcpy(dst, dmaaddr, AlphaISA::PageBytes);
@@ -154,7 +156,7 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
if (cplen > 0) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
assert(dmaaddr);
memcpy(dst, dmaaddr, cplen);
@@ -172,7 +174,7 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
paddr = vtophys(xc, dest);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)cplen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
memcpy(dmaaddr, src, len);
@@ -185,7 +187,8 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
memcpy(dmaaddr, src, AlphaISA::PageBytes);
@@ -196,7 +199,7 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
if (cplen > 0) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
assert(dmaaddr);
memcpy(dmaaddr, src, cplen);
@@ -213,7 +216,7 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
paddr = vtophys(xc, vaddr);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)maxlen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, len);
@@ -231,7 +234,8 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
while (maxlen > AlphaISA::PageBytes) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
@@ -248,7 +252,7 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
if (maxlen > 0) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, maxlen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, maxlen);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, maxlen);
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index 21a2ce696..570110d84 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.
@@ -207,8 +224,8 @@ def p_specification(t):
namespace = isa_name + "Inst"
# wrap the decode block as a function definition
t[4].wrap_decode_block('''
-StaticInstPtr<%(isa_name)s>
-%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst)
+StaticInstPtr
+%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
{
using namespace %(namespace)s;
''' % vars(), '}')
@@ -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.
@@ -606,43 +712,6 @@ yacc.yacc()
#
#####################################################################
-################
-# CpuModel class
-#
-# The CpuModel class encapsulates everything we need to know about a
-# particular CPU model.
-
-class CpuModel:
- # List of all CPU models. Accessible as CpuModel.list.
- list = []
-
- # Constructor. Automatically adds models to CpuModel.list.
- def __init__(self, name, filename, includes, strings):
- self.name = name
- self.filename = filename # filename for output exec code
- self.includes = includes # include files needed in exec file
- # The 'strings' dict holds all the per-CPU symbols we can
- # substitute into templates etc.
- self.strings = strings
- # Add self to list.
- CpuModel.list.append(self)
-
-# Define CPU models. The following lines should contain the only
-# CPU-model-specific information in this file. Note that the ISA
-# description itself should have *no* CPU-model-specific content.
-CpuModel('SimpleCPU', 'simple_cpu_exec.cc',
- '#include "cpu/simple/cpu.hh"',
- { 'CPU_exec_context': 'SimpleCPU' })
-CpuModel('FastCPU', 'fast_cpu_exec.cc',
- '#include "cpu/fast/cpu.hh"',
- { 'CPU_exec_context': 'FastCPU' })
-#CpuModel('FullCPU', 'full_cpu_exec.cc',
-# '#include "encumbered/cpu/full/dyn_inst.hh"',
-# { 'CPU_exec_context': 'DynInst' })
-CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
- '#include "cpu/o3/alpha_dyn_inst.hh"',
- { 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
-
# Expand template with CPU-specific references into a dictionary with
# an entry for each CPU model name. The entry key is the model name
# and the corresponding value is the template with the CPU-specific
@@ -651,7 +720,7 @@ def expand_cpu_symbols_to_dict(template):
# Protect '%'s that don't go with CPU-specific terms
t = re.sub(r'%(?!\(CPU_)', '%%', template)
result = {}
- for cpu in CpuModel.list:
+ for cpu in cpu_models:
result[cpu.name] = t % cpu.strings
return result
@@ -710,7 +779,7 @@ class GenCode:
# concatenates all the individual strings in the operands.
def __add__(self, other):
exec_output = {}
- for cpu in CpuModel.list:
+ for cpu in cpu_models:
n = cpu.name
exec_output[n] = self.exec_output[n] + other.exec_output[n]
return GenCode(self.header_output + other.header_output,
@@ -724,7 +793,7 @@ class GenCode:
self.header_output = pre + self.header_output
self.decoder_output = pre + self.decoder_output
self.decode_block = pre + self.decode_block
- for cpu in CpuModel.list:
+ for cpu in cpu_models:
self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
# Wrap the decode block in a pair of strings (e.g., 'case foo:'
@@ -739,6 +808,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 +843,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 +905,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 +932,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 +1038,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 +1141,249 @@ 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:
- c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
- c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ if self.is_src:
+ c += '\n\t_srcRegIdx[%d] = %s;' % \
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
+ c += '\n\t_destRegIdx[%d] = %s;' % \
+ (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)
+ base = 'xc->readMiscReg(%s)' % self.reg_spec
+ 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->setMiscReg(%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):
+ return ''
- def makeWrite(self, op_desc):
- return 'xc->setNextPC(%s);\n' % op_desc.munged_name
+ # 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
-exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
- 'ControlRegOperandTraits', 'MemOperandTraits',
- 'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
- 're', 'string')
+class NPCOperand(Operand):
+ def makeConstructor(self):
+ return ''
-exportContext = {}
+ def makeRead(self):
+ return '%s = xc->readPC() + 4;\n' % self.base_name
-def updateExportContext():
- exportContext.update(exportDict(*exportContextSymbols))
- exportContext.update(templateMap)
+ def makeWrite(self):
+ return 'xc->setNextPC(%s);\n' % self.base_name
+class NNPCOperand(Operand):
+ def makeConstructor(self):
+ return ''
-def exportDict(*symNames):
- return dict([(s, eval(s)) for s in symNames])
+ def makeRead(self):
+ return '%s = xc->readPC() + 8;\n' % self.base_name
+ def makeWrite(self):
+ return 'xc->setNextNPC(%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 +1405,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 +1515,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 +1525,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 +1553,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 +1567,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.
@@ -1575,6 +1659,8 @@ namespace %(namespace)s {
%(namespace_output)s
} // namespace %(namespace)s
+
+%(decode_function)s
'''
@@ -1601,19 +1687,48 @@ 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.
#
-def parse_isa_desc(isa_desc_file, output_dir, include_path):
+def parse_isa_desc(isa_desc_file, output_dir):
# set a global var for the input filename... used in error messages
global input_filename
input_filename = isa_desc_file
+ 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)
@@ -1625,24 +1740,33 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path):
includes = '#include "base/bitfield.hh" // for bitfield support'
global_output = global_code.header_output
namespace_output = namespace_code.header_output
+ decode_function = ''
update_if_needed(output_dir + '/decoder.hh', file_template % vars())
# generate decoder.cc
- includes = '#include "%s/decoder.hh"' % include_path
+ includes = '#include "decoder.hh"'
global_output = global_code.decoder_output
namespace_output = namespace_code.decoder_output
- namespace_output += namespace_code.decode_block
+ # namespace_output += namespace_code.decode_block
+ decode_function = namespace_code.decode_block
update_if_needed(output_dir + '/decoder.cc', file_template % vars())
# generate per-cpu exec files
- for cpu in CpuModel.list:
- includes = '#include "%s/decoder.hh"\n' % include_path
+ for cpu in cpu_models:
+ includes = '#include "decoder.hh"\n'
includes += cpu.includes
global_output = global_code.exec_output[cpu.name]
namespace_output = namespace_code.exec_output[cpu.name]
+ decode_function = ''
update_if_needed(output_dir + '/' + cpu.filename,
file_template % vars())
+# global list of CpuModel objects (see cpu_models.py)
+cpu_models = []
+
# Called as script: get args from command line.
+# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
if __name__ == '__main__':
- parse_isa_desc(sys.argv[1], sys.argv[2], sys.argv[3])
+ execfile(sys.argv[1]) # read in CpuModel definitions
+ cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
+ parse_isa_desc(sys.argv[2], sys.argv[3])
diff --git a/arch/isa_specific.hh b/arch/isa_specific.hh
new file mode 100644
index 000000000..44f8e9d64
--- /dev/null
+++ b/arch/isa_specific.hh
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ISA_SPECIFIC_HH__
+#define __ARCH_ISA_SPECIFIC_HH__
+
+//This file provides a mechanism for other source code to bring in
+//files from the ISA being compiled with
+
+//These are constants so you can selective compile code based on the isa
+//To use them, do something like
+//
+//#if THE_ISA == YOUR_FAVORITE_ISA
+// conditional_code
+//#endif
+//
+//Note that this is how this file sets up the other isa "hooks"
+
+//These macros have numerical values because otherwise the preprocessor
+//would treat them as 0 in comparisons.
+#define ALPHA_ISA 21064
+#define SPARC_ISA 42
+#define MIPS_ISA 1337
+
+//These tell the preprocessor where to find the files of a particular
+//ISA, and set the "TheISA" macro for use elsewhere.
+#if THE_ISA == ALPHA_ISA
+ #define TheISA AlphaISA
+#elif THE_ISA == SPARC_ISA
+ #define TheISA SparcISA
+#elif THE_ISA == MIPS_ISA
+ #define TheISA MipsISA
+#else
+ #error "THE_ISA not set"
+#endif
+
+#endif
diff --git a/arch/mips/SConscript b/arch/mips/SConscript
new file mode 100644
index 000000000..b8efa7ef9
--- /dev/null
+++ b/arch/mips/SConscript
@@ -0,0 +1,83 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ memory.cc
+ arguments.cc
+ mips34k.cc
+ osfpal.cc
+ stacktrace.cc
+ vtophys.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ common_syscall_emul.cc
+ linux_process.cc
+ tru64_process.cc
+ ''')
+
+# Set up complete list of sources based on configuration.
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/arch/mips/faults.cc b/arch/mips/faults.cc
new file mode 100644
index 000000000..142dfe0a4
--- /dev/null
+++ b/arch/mips/faults.cc
@@ -0,0 +1,80 @@
+/*
+ * 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/faults.hh"
+
+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);
+
+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/mips/faults.hh b/arch/mips/faults.hh
new file mode 100644
index 000000000..c1cb956b0
--- /dev/null
+++ b/arch/mips/faults.hh
@@ -0,0 +1,160 @@
+/*
+ * 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 __MIPS_FAULTS_HH__
+#define __MIPS_FAULTS_HH__
+
+#include "sim/faults.hh"
+#include "arch/isa_traits.hh" //For the Addr type
+
+class MipsFault : public FaultBase
+{
+ public:
+ MipsFault(char * newName, int newId, Addr newVect)
+ : FaultBase(newName, newId), vect(newVect)
+ {;}
+
+ Addr vect;
+};
+
+extern class ResetFaultType : public MipsFault
+{
+ public:
+ ResetFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const ResetFault;
+
+extern class ArithmeticFaultType : public MipsFault
+{
+ public:
+ ArithmeticFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const ArithmeticFault;
+
+extern class InterruptFaultType : public MipsFault
+{
+ public:
+ InterruptFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const InterruptFault;
+
+extern class NDtbMissFaultType : public MipsFault
+{
+ public:
+ NDtbMissFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const NDtbMissFault;
+
+extern class PDtbMissFaultType : public MipsFault
+{
+ public:
+ PDtbMissFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const PDtbMissFault;
+
+extern class DtbPageFaultType : public MipsFault
+{
+ public:
+ DtbPageFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const DtbPageFault;
+
+extern class DtbAcvFaultType : public MipsFault
+{
+ public:
+ DtbAcvFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const DtbAcvFault;
+
+extern class ItbMissFaultType : public MipsFault
+{
+ public:
+ ItbMissFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const ItbMissFault;
+
+extern class ItbPageFaultType : public MipsFault
+{
+ public:
+ ItbPageFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const ItbPageFault;
+
+extern class ItbAcvFaultType : public MipsFault
+{
+ public:
+ ItbAcvFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const ItbAcvFault;
+
+extern class UnimplementedOpcodeFaultType : public MipsFault
+{
+ public:
+ UnimplementedOpcodeFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const UnimplementedOpcodeFault;
+
+extern class FloatEnableFaultType : public MipsFault
+{
+ public:
+ FloatEnableFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const FloatEnableFault;
+
+extern class PalFaultType : public MipsFault
+{
+ public:
+ PalFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const PalFault;
+
+extern class IntegerOverflowFaultType : public MipsFault
+{
+ public:
+ IntegerOverflowFaultType(char * newName, int newId, Addr newVect)
+ : MipsFault(newName, newId, newVect)
+ {;}
+} * const IntegerOverflowFault;
+
+extern Fault ** ListOfFaults[];
+extern int NumFaults;
+
+#endif // __FAULTS_HH__
diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa
new file mode 100644
index 000000000..4125b5101
--- /dev/null
+++ b/arch/mips/isa/base.isa
@@ -0,0 +1,96 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Base class for MIPS instructions, and some support functions
+//
+
+//Outputs to decoder.hh
+output header {{
+
+#define R31 31
+#include "arch/mips/faults.hh"
+#include "arch/mips/isa_traits.hh"
+
+ using namespace MipsISA;
+
+
+ /**
+ * Base class for all MIPS static instructions.
+ */
+ class MipsStaticInst : public StaticInst
+ {
+ protected:
+
+ /// Make MipsISA register dependence tags directly visible in
+ /// this class and derived classes. Maybe these should really
+ /// live here and not in the MipsISA namespace.
+ /*enum DependenceTags {
+ FP_Base_DepTag = MipsISA::FP_Base_DepTag,
+ Fpcr_DepTag = MipsISA::Fpcr_DepTag,
+ Uniq_DepTag = MipsISA::Uniq_DepTag,
+ IPR_Base_DepTag = MipsISA::IPR_Base_DepTag
+ };*/
+
+ // Constructor
+ MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : StaticInst(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;
+ };
+
+}};
+
+//Ouputs to decoder.cc
+output decoder {{
+
+ void MipsStaticInst::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 MipsStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if(_numSrcRegs > 0)
+ {
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ if(_numSrcRegs > 1)
+ {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if(_numDestRegs > 0)
+ {
+ if(_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+
+}};
+
diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa
new file mode 100644
index 000000000..58d487ad2
--- /dev/null
+++ b/arch/mips/isa/bitfields.isa
@@ -0,0 +1,67 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+def bitfield OPCODE <31:26>;
+def bitfield OPCODE_HI <31:29>;
+def bitfield OPCODE_LO <28:26>;
+
+def bitfield REGIMM <20:16>;
+def bitfield REGIMM_HI <20:19>;
+def bitfield REGIMM_LO <18:16>;
+
+def bitfield FUNCTION < 5: 0>;
+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 FR <25:21>;
+def bitfield FT <20:16>;
+def bitfield FS <15:11>;
+def bitfield FD <10:6>;
+
+def bitfield CC <20:18>;
+def bitfield ND <17:17>;
+def bitfield TF <16:16>;
+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>;
+
+// CP0 Register Select
+def bitfield SEL < 2: 0>;
+
+// Interrupts
+def bitfield SC < 5: 5>;
+
+// Branch format
+def bitfield OFFSET <15: 0>; // displacement
+
+// Jmp format
+def bitfield JMPTARG <25: 0>;
+def bitfield HINT <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..3f054f6a5
--- /dev/null
+++ b/arch/mips/isa/decoder.isa
@@ -0,0 +1,930 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// 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 {
+
+ 0x0: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_LO {
+ 0x1: decode MOVCI {
+ format BasicOp {
+ 0: movf({{ if (xc->readMiscReg(FPCR,0) != CC) Rd = Rs}});
+ 1: movt({{ if (xc->readMiscReg(FPCR,0) == CC) 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: decode RS {
+ 0x0: decode RT default BasicOp::sll({{ Rd = Rt.uw << SA; }}) {
+ 0x0: decode RD{
+ 0x0: decode HINT {
+ 0x0:nop({{}}); //really sll r0,r0,0
+ 0x1:ssnop({{}});//really sll r0,r0,1
+ 0x3:ehb({{}}); //really sll r0,r0,3
+ }
+ }
+ }
+ }
+
+ 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: decode HINT {
+ 0:jr({{ NNPC = Rs & ~1; }},IsReturn);
+
+ 1:jr_hb({{ NNPC = Rs & ~1; clear_exe_inst_hazards(); }},IsReturn);
+ }
+
+ 0x1: decode HINT {
+ 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn);
+
+ 1: jalr_hb({{ NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn);
+ }
+ }
+
+ format BasicOp {
+ 0x2: movz({{ if (Rt == 0) Rd = Rs; }});
+ 0x3: movn({{ if (Rt != 0) Rd = Rs; }});
+ }
+
+ format WarnUnimpl {
+ 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative
+ 0x5: break();
+ 0x7: sync();
+ }
+ }
+
+ 0x2: decode FUNCTION_LO {
+ format BasicOp {
+ 0x0: mfhi({{ Rd = xc->readMiscReg(Hi); }});
+ 0x1: mthi({{ xc->setMiscReg(Hi,Rs); }});
+ 0x2: mflo({{ Rd = xc->readMiscReg(Lo); }});
+ 0x3: mtlo({{ xc->setMiscReg(Lo,Rs); }});
+ }
+ }
+
+ 0x3: decode FUNCTION_LO {
+ format IntOp {
+ 0x0: mult({{
+ int64_t temp1 = Rs.sw * Rt.sw;
+ xc->setMiscReg(Hi,temp1<63:32>);
+ xc->setMiscReg(Lo,temp1<31:0>);
+ }});
+
+ 0x1: multu({{
+ int64_t temp1 = Rs.uw * Rt.uw;
+ xc->setMiscReg(Hi,temp1<63:32>);
+ xc->setMiscReg(Lo,temp1<31:0>);
+ }});
+
+ 0x2: div({{
+ xc->setMiscReg(Hi,Rs.sw % Rt.sw);
+ xc->setMiscReg(Lo,Rs.sw / Rt.sw);
+ }});
+
+ 0x3: divu({{
+ xc->setMiscReg(Hi,Rs.uw % Rt.uw);
+ xc->setMiscReg(Lo,Rs.uw / Rt.uw);
+ }});
+ }
+ }
+
+ 0x4: decode FUNCTION_LO {
+ format IntOp {
+ 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;/*Trap on Overflow*/}});
+ 0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}});
+ 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}});
+ 0x3: subu({{ Rd.sw = Rs.sw - Rt.uw;}});
+ 0x4: and({{ Rd = Rs & Rt;}});
+ 0x5: or({{ Rd = Rs | Rt;}});
+ 0x6: xor({{ Rd = Rs ^ Rt;}});
+ 0x7: nor({{ Rd = ~(Rs | Rt);}});
+ }
+ }
+
+ 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 Branch {
+ 0x0: bltz({{ cond = (Rs.sw < 0); }});
+ 0x1: bgez({{ cond = (Rs.sw >= 0); }});
+ }
+
+ format BranchLikely {
+ //MIPS obsolete instructions
+ 0x2: bltzl({{ cond = (Rs.sw < 0); }});
+ 0x3: bgezl({{ cond = (Rs.sw >= 0); }});
+ }
+ }
+
+ 0x1: decode REGIMM_LO {
+ format Trap {
+ 0x0: tgei( {{ cond = (Rs.sw >= INTIMM); }});
+ 0x1: tgeiu({{ cond = (Rs.uw >= INTIMM); }});
+ 0x2: tlti( {{ cond = (Rs.sw < INTIMM); }});
+ 0x3: tltiu({{ cond = (Rs.uw < INTIMM); }});
+ 0x4: teqi( {{ cond = (Rs.sw == INTIMM);}});
+ 0x6: tnei( {{ cond = (Rs.sw != INTIMM);}});
+ }
+ }
+
+ 0x2: decode REGIMM_LO {
+ format Branch {
+ 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsCall,IsReturn);
+ 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsCall,IsReturn);
+ }
+
+ format BranchLikely {
+ //Will be removed in future MIPS releases
+ 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn);
+ 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn);
+ }
+ }
+
+ 0x3: decode REGIMM_LO {
+ format WarnUnimpl {
+ 0x7: synci();
+ }
+ }
+ }
+
+ format Jump {
+ 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2);}});
+
+ 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},IsCall,IsReturn);
+ }
+
+ format Branch {
+ 0x4: beq({{ cond = (Rs.sw == Rt.sw); }});
+ 0x5: bne({{ cond = (Rs.sw != Rt.sw); }});
+ 0x6: blez({{ cond = (Rs.sw <= 0); }});
+ 0x7: bgtz({{ cond = (Rs.sw > 0); }});
+ }
+ }
+
+ 0x1: decode OPCODE_LO {
+ format IntOp {
+ 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}});
+ 0x1: addiu({{ Rt.sw = Rs.sw + imm;}});
+ 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }});
+ 0x3: sltiu({{ Rt.sw = ( Rs.sw < imm ) ? 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 {
+
+ //Table A-11 MIPS32 COP0 Encoding of rs Field
+ 0x0: decode RS_MSB {
+ 0x0: decode RS {
+ format System {
+ 0x0: mfc0({{
+ //uint64_t reg_num = Rd.uw;
+
+ Rt = xc->readMiscReg(RD << 5 | SEL);
+ }});
+
+ 0x4: mtc0({{
+ //uint64_t reg_num = Rd.uw;
+
+ xc->setMiscReg(RD << 5 | SEL,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->readMiscReg(SRSCtl)/*[PSS]*/;
+ //uint64_t reg_num = Rt.uw;
+
+ //Rd = xc->regs.IntRegFile[prev];
+ //Rd = xc->shadowIntRegFile[prev][reg_num];
+ }});
+
+ 0xB: decode RD {
+
+ 0x0: decode SC {
+ 0x0: dvpe({{
+ int idx;
+ int sel;
+ getMiscRegIdx(MVPControl,idx,sel);
+ Rt.sw = xc->readMiscReg(idx,sel);
+ xc->setMiscReg(idx,sel);
+ }});
+
+ 0x1: evpe({{
+ int idx;
+ int sel;
+ getMiscRegIdx(MVPControl,idx,sel);
+ Rt.sw = xc->readMiscReg(idx,sel);
+ xc->setMiscReg(idx,sel,1);
+ }});
+ }
+
+ 0x1: decode SC {
+ 0x0: dmt({{
+ int idx;
+ int sel;
+ getMiscRegIdx(VPEControl,idx,sel);
+ Rt.sw = xc->readMiscReg(idx,sel);
+ xc->setMiscReg(idx,sel);
+ }});
+
+ 0x1: emt({{
+ int idx;
+ int sel;
+ getMiscRegIdx(VPEControl,idx,sel);
+ Rt.sw = xc->readMiscReg(idx,sel);
+ xc->setMiscReg(idx,sel,1);
+ }});
+ }
+
+ 0xC: decode SC {
+ 0x0: di({{
+ int idx;
+ int sel;
+ getMiscRegIdx(Status,idx,sel);
+ Rt.sw = xc->readMiscReg(idx,sel);
+ xc->setMiscReg(idx,sel);
+ }});
+
+ 0x1: ei({{
+ int idx;
+ int sel;
+ getMiscRegIdx(Status,idx,sel);
+ Rt.sw = xc->readMiscReg(idx,sel);
+ xc->setMiscReg(idx,sel,1);
+ }});
+ }
+ }
+
+ 0xE: wrpgpr({{
+ //Accessing Previous Shadow Set Register Number
+ //uint64_t prev = xc->readMiscReg(SRSCtl/*[PSS]*/);
+ //uint64_t reg_num = Rd.uw;
+
+ //xc->regs.IntRegFile[prev];
+ //xc->shadowIntRegFile[prev][reg_num] = Rt;
+ }});
+ }
+ }
+
+ //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO
+ 0x1: decode FUNCTION {
+ format System {
+ 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.uw = Fs.ud<31:0>;*/ }});
+ 0x2: cfc1({{ /*Rt.uw = xc->readMiscReg(FPCR[Fs]);*/}});
+ 0x3: mfhc1({{ /*Rt.uw = Fs.ud<63:32>*/;}});
+ 0x4: mtc1({{ /*Fs = Rt.uw*/}});
+ 0x6: ctc1({{ /*xc->setMiscReg(FPCR[Fs],Rt);*/}});
+ 0x7: mthc1({{ /*Fs<63:32> = Rt.uw*/}});
+ }
+ }
+
+ 0x1: decode ND {
+ 0x0: decode TF {
+ format Branch {
+ 0x0: bc1f({{ cond = (xc->readMiscReg(FPCR) == 0); }});
+ 0x1: bc1t({{ cond = (xc->readMiscReg(FPCR) == 1); }});
+ }
+ }
+
+ 0x1: decode TF {
+ format BranchLikely {
+ 0x0: bc1fl({{ cond = (xc->readMiscReg(FPCR) == 0); }});
+ 0x1: bc1tl({{ cond = (xc->readMiscReg(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 = fabs(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 (xc->readMiscReg(FPCR) != CC) Fd = Fs; }});
+ 0x1: movts({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}});
+ }
+ }
+
+ format BasicOp {
+ 0x2: movzs({{ if (Rt == 0) Fd = Fs; }});
+ 0x3: movns({{ if (Rt != 0) Fd = Fs; }});
+ }
+
+ format Float64Op {
+ 0x5: recips({{ Fd = 1 / Fs; }});
+ 0x6: rsqrts({{ Fd = 1 / sqrt((double)Fs.ud);}});
+ }
+ }
+
+ 0x4: decode RS_LO {
+
+ format FloatOp {
+ 0x1: cvt_d_s({{ int rnd_mode = xc->readMiscReg(FCSR);
+ Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE);
+ }});
+
+ 0x4: cvt_w_s({{ int rnd_mode = xc->readMiscReg(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->readMiscReg(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 = fabs(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 (xc->readMiscReg(FPCR) != CC) Fd.df = Fs.df; }});
+ 0x1: movtd({{if (xc->readMiscReg(FPCR) == CC) Fd.df = Fs.df; }});
+ }
+ }
+
+ format BasicOp {
+ 0x2: movzd({{ if (Rt == 0) Fd.df = Fs.df; }});
+ 0x3: movnd({{ 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->readMiscReg(FCSR);
+ Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE);
+ }});
+
+ 0x4: cvt_w_d({{
+ int rnd_mode = xc->readMiscReg(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->readMiscReg(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 {
+ 0x20: cvt_s({{
+ int rnd_mode = xc->readMiscReg(FCSR);
+ Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD);
+ }});
+
+ 0x21: cvt_d({{
+ int rnd_mode = xc->readMiscReg(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->readMiscReg(FCSR);
+ Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG);
+ }});
+
+ 0x11: cvt_d_l({{
+ int rnd_mode = xc->readMiscReg(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 = fabs(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 (xc->readMiscReg(FPCR) != CC) Fd = Fs;}});
+ 0x1: movtps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}});
+ }
+ }
+
+ format BasicOp {
+ 0x2: movzps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }});
+ 0x3: movnps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs; }});
+ }
+
+ }
+
+ 0x4: decode RS_LO {
+ 0x0: Float64Op::cvt_s_pu({{
+ int rnd_mode = xc->readMiscReg(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->readMiscReg(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 LoadMemory2 {
+ 0x0: lwxc1({{ EA = Rs + Rt; }},{{ /*F_t<31:0> = Mem.sf; */}});
+ 0x1: ldxc1({{ EA = Rs + Rt; }},{{ /*F_t<63:0> = Mem.df;*/ }});
+ 0x5: luxc1({{ //Need to make EA<2:0> = 0
+ EA = Rs + Rt;
+ }},
+ {{ /*F_t<31:0> = Mem.df; */}});
+ }
+ }
+
+ 0x1: decode FUNCTION_LO {
+ format StoreMemory2 {
+ 0x0: swxc1({{ EA = Rs + Rt; }},{{ /*Mem.sf = Ft<31:0>; */}});
+ 0x1: sdxc1({{ EA = Rs + Rt; }},{{ /*Mem.df = Ft<63:0> */}});
+ 0x5: suxc1({{ //Need to make EA<2:0> = 0
+ EA = Rs + Rt;
+ }},
+ {{ /*Mem.df = F_t<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 BranchLikely {
+ 0x4: beql({{ cond = (Rs.sw == 0); }});
+ 0x5: bnel({{ cond = (Rs.sw != 0); }});
+ 0x6: blezl({{ cond = (Rs.sw <= 0); }});
+ 0x7: bgtzl({{ cond = (Rs.sw > 0); }});
+ }
+ }
+
+ 0x3: decode OPCODE_LO default FailUnimpl::reserved() {
+
+ //Table A-5 MIPS32 SPECIAL2 Encoding of Function Field
+ 0x4: decode FUNCTION_HI {
+
+ 0x0: decode FUNCTION_LO {
+ format IntOp {
+ 0x0: madd({{
+ int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ temp1 = temp1 + (Rs.sw * Rt.sw);
+ xc->setMiscReg(Hi,temp1<63:32>);
+ xc->setMiscReg(Lo,temp1<31:0>);
+ }});
+
+ 0x1: maddu({{
+ int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ temp1 = temp1 + (Rs.uw * Rt.uw);
+ xc->setMiscReg(Hi,temp1<63:32>);
+ xc->setMiscReg(Lo,temp1<31:0>);
+ }});
+
+ 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }});
+
+ 0x4: msub({{
+ int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ temp1 = temp1 - (Rs.sw * Rt.sw);
+ xc->setMiscReg(Hi,temp1<63:32>);
+ xc->setMiscReg(Lo,temp1<31:0>);
+ }});
+
+ 0x5: msubu({{
+ int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ temp1 = temp1 - (Rs.uw * Rt.uw);
+ xc->setMiscReg(Hi,temp1<63:32>);
+ xc->setMiscReg(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 LoadMemory {
+ 0x0: lb({{ Rt.sw = Mem.sb; }});
+ 0x1: lh({{ Rt.sw = Mem.sh; }});
+ 0x2: lwl({{ Rt.sw = Mem.sw; }});//, WordAlign);
+ 0x3: lw({{ Rt.sw = Mem.sb; }});
+ 0x4: lbu({{ Rt.uw = Mem.ub; }});
+ 0x5: lhu({{ Rt.uw = Mem.uh; }});
+ 0x6: lwr({{ Rt.uw = Mem.uw; }});//, WordAlign);
+ }
+
+ 0x7: FailUnimpl::reserved();
+ }
+
+ 0x5: decode OPCODE_LO default FailUnimpl::reserved() {
+ format StoreMemory {
+ 0x0: sb({{ Mem.ub = Rt<7:0>; }});
+ 0x1: sh({{ Mem.uh = Rt<15:0>; }});
+ 0x2: swl({{ Mem.ub = Rt<31:0>; }});//,WordAlign);
+ 0x3: sw({{ Mem.ub = Rt<31:0>; }});
+ 0x6: swr({{ Mem.ub = Rt<31:0>; }});//,WordAlign);
+ }
+
+ format WarnUnimpl {
+ 0x7: cache();
+ }
+
+ }
+
+ 0x6: decode OPCODE_LO default FailUnimpl::reserved() {
+ 0x0: WarnUnimpl::ll();
+
+ format LoadMemory {
+ 0x1: lwc1({{ /*F_t<31:0> = Mem.sf; */}});
+ 0x5: ldc1({{ /*F_t<63:0> = Mem.df; */}});
+ }
+ }
+
+
+ 0x7: decode OPCODE_LO default FailUnimpl::reserved() {
+ 0x0: WarnUnimpl::sc();
+
+ format StoreMemory {
+ 0x1: swc1({{ //Mem.sf = Ft<31:0>; }});
+ 0x5: sdc1({{ //Mem.df = Ft<63:0>; }});
+ }
+ }
+}
+
+
diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa
new file mode 100644
index 000000000..f7a9e4ce2
--- /dev/null
+++ b/arch/mips/isa/formats.isa
@@ -0,0 +1,35 @@
+// -*- mode:c++ -*-
+
+//Templates from this format are used later
+//Include the basic format
+##include "m5/arch/mips/isa/formats/basic.isa"
+
+//Include the basic format
+##include "m5/arch/mips/isa/formats/noop.isa"
+
+//Include utility formats/functions
+##include "m5/arch/mips/isa/formats/util.isa"
+
+//Include the cop0 formats
+##include "m5/arch/mips/isa/formats/cop0.isa"
+
+//Include the integer formats
+##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/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..c02af7ddc
--- /dev/null
+++ b/arch/mips/isa/formats/basic.isa
@@ -0,0 +1,66 @@
+// -*- mode:c++ -*-
+
+// 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 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..0d2ad7855
--- /dev/null
+++ b/arch/mips/isa/formats/branch.isa
@@ -0,0 +1,322 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
+
+output header {{
+
+#include <iostream>
+ using namespace std;
+
+ /**
+ * Base class for instructions whose disassembly is not purely a
+ * function of the machine instruction (i.e., it depends on the
+ * PC). This class overrides the disassemble() method to check
+ * the PC and symbol table values before re-using a cached
+ * disassembly string. This is necessary for branches and jumps,
+ * where the disassembly string includes the target address (which
+ * may depend on the PC and/or symbol table).
+ */
+ class PCDependentDisassembly : public MipsStaticInst
+ {
+ protected:
+ /// Cached program counter from last disassembly
+ mutable Addr cachedPC;
+
+ /// Cached symbol table pointer from last disassembly
+ mutable const SymbolTable *cachedSymtab;
+
+ /// Constructor
+ PCDependentDisassembly(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : MipsStaticInst(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ 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:
+ /// target address (signed) Displacement .
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+ //If Bit 17 is 1 then Sign Extend
+ if ( (disp & 0x00020000) > 0 ) {
+ disp |= 0xFFFE0000;
+ }
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branch likely branches (PC-relative control transfers),
+ */
+ class BranchLikely : public PCDependentDisassembly
+ {
+ protected:
+ /// target address (signed) Displacement .
+ int32_t disp;
+
+ /// Constructor.
+ BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for jumps (register-indirect control transfers). In
+ * the Mips ISA, these are always unconditional.
+ */
+ class Jump : public PCDependentDisassembly
+ {
+ protected:
+
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ uint32_t target;
+
+ public:
+ /// Constructor
+ Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(JMPTARG << 2)
+ {
+ }
+
+ 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
+ BranchLikely::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 4 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ExecContext *xc) const
+ {
+ Addr NPC = xc->readPC() + 4;
+ uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
+ {
+ 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 == 1) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ } else if(_numSrcRegs == 2) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ ss << ",";
+ }
+
+ Addr target = pc + 8 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // There's only one register arg (RA), but it could be
+ // either a source (the condition for conditional
+ // branches) or a destination (the link reg for
+ // unconditional branches)
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+ else if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+ 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);
+
+ if ( mnemonic == "jal" ) {
+ Addr npc = pc + 4;
+ ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
+ } else if (_numSrcRegs == 0) {
+ std::string str;
+ if (symtab && symtab->findSymbol(disp, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", disp);
+ } else if (_numSrcRegs == 1) {
+ printReg(ss, _srcRegIdx[0]);
+ } else if(_numSrcRegs == 2) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ } else {
+ panic(">= 3 Source Registers!!!");
+ }
+
+ return ss.str();
+ }
+}};
+
+def format Branch(code,*flags) {{
+ #Add Link Code if Link instruction
+ strlen = len(name)
+ if name[strlen-2:] == 'al':
+ code += 'r31 = NNPC;\n'
+
+ #Condition code
+ code = 'bool cond;\n' + code
+ code += 'if (cond) {\n'
+ code += ' NNPC = NPC + disp;\n'
+ code += '} else {\n'
+ code += ' NNPC = NNPC;\n'
+ code += '} \n'
+
+ code += 'cout << hex << "NPC: " << NPC << " + " << disp << " = " << NNPC << endl;'
+
+ iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
+ ('IsDirectControl', 'IsCondControl'))
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+def format BranchLikely(code,*flags) {{
+ #Add Link Code if Link instruction
+ strlen = len(name)
+ if name[strlen-3:] == 'all':
+ code += 'r31 = NNPC;\n'
+
+ #Condition code
+ code = 'bool cond;\n' + code
+ code += 'if (cond) {'
+ code += 'NNPC = NPC + disp;\n'
+ code += '} \n'
+
+
+ iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
+ ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format Jump(code,*flags) {{
+ #Add Link Code if Link instruction
+ strlen = len(name)
+ if strlen > 1 and name[1:] == 'al':
+ code = 'r31 = NNPC;\n' + code
+
+ #code += 'if(NNPC == 0x80000638) { NNPC = r31; cout << "SKIPPING JUMP TO SIM_GET_MEM_CONF" << endl;}'
+ #code += 'target = NNPC;'
+
+ iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
+ ('IsIndirectControl', 'IsUncondControl'))
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+
+
diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa
new file mode 100644
index 000000000..34b71acf7
--- /dev/null
+++ b/arch/mips/isa/formats/fp.isa
@@ -0,0 +1,49 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Floating Point operate instructions
+//
+
+output header {{
+ /**
+ * Base class for FP 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";
+ }
+}};
+
+
+// Primary format for integer operate instructions:
+def format FloatOp(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)
+}};
+
+// Primary format for integer operate instructions:
+def format Float64Op(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/int.isa b/arch/mips/isa/formats/int.isa
new file mode 100644
index 000000000..a47844bee
--- /dev/null
+++ b/arch/mips/isa/formats/int.isa
@@ -0,0 +1,130 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Integer operate instructions
+//
+
+//Outputs to decoder.hh
+output header {{
+#include <iostream>
+ using namespace std;
+ /**
+ * Base class for integer operations.
+ */
+ class IntOp : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ IntOp(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:
+
+ int32_t imm;
+
+ /// Constructor
+ IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM)
+ {
+ //If Bit 15 is 1 then Sign Extend
+ int32_t temp = imm & 0x00008000;
+
+ if (temp > 0 && mnemonic != "lui") {
+ imm |= 0xFFFF0000;
+ }
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+
+ };
+
+}};
+
+//Outputs to decoder.cc
+output decoder {{
+ std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ ss << ",";
+
+ // 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]);
+ }
+
+ return ss.str();
+ }
+
+ std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ ss << ",";
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+
+ if( mnemonic == "lui")
+ ccprintf(ss, "%08p ", imm);
+ else
+ ss << (int) imm;
+
+ return ss.str();
+ }
+
+}};
+
+//Used by decoder.isa
+def format IntOp(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+
+ # Figure out if we are creating a IntImmOp or a IntOp
+ # by looking at the instruction name
+ iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags)
+ strlen = len(name)
+ if name[strlen-1] == 'i' or name[strlen-2:] == 'iu':
+ iop = InstObjParams(name, Name, '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..8a07e63d4
--- /dev/null
+++ b/arch/mips/isa/formats/mem.isa
@@ -0,0 +1,469 @@
+// -*- 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 Mips memory-format instructions.
+ */
+ class Memory : public MipsStaticInst
+ {
+ protected:
+
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+
+ /// Constructor
+ Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : MipsStaticInst(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
+ disp(OFFSET)
+ {
+ //If Bit 15 is 1 then Sign Extend
+ int32_t temp = disp & 0x00008000;
+
+ if (temp > 0) {
+ disp |= 0xFFFF0000;
+ }
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr &memAccInst() const { return memAccPtr; }
+ };
+
+}};
+
+
+output decoder {{
+ std::string
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
+ flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
+ }
+
+}};
+
+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;
+ }
+}};
+
+// load instructions use Rt as dest, so check for
+// Rt == 31 to detect nops
+def template LoadNopCheckDecode {{
+ {
+ MipsStaticInst *i = new %(class_name)s(machInst);
+ if (RT == 0) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Load')
+}};
+
+
+def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ exec_template_base = 'Store')
+}};
+
+//FP loads are offloaded to these formats for now ...
+def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Load')
+}};
+
+
+//FP stores are offloaded to these formats for now ...
+def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Store')
+}};
+
diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa
new file mode 100644
index 000000000..d35179005
--- /dev/null
+++ b/arch/mips/isa/formats/noop.isa
@@ -0,0 +1,90 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
+
+output header {{
+ /**
+ * Static instruction class for no-ops. This is a leaf class.
+ */
+ class Nop : public MipsStaticInst
+ {
+ /// Disassembly of original instruction.
+ const std::string originalDisassembly;
+
+ public:
+ /// Constructor
+ Nop(const std::string _originalDisassembly, MachInst _machInst)
+ : MipsStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ 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
+ MipsStaticInst *
+ makeNop(MipsStaticInst *inst)
+ {
+ MipsStaticInst *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 RT as dest, so check for
+// RT == 0 to detect nops
+def template OperateNopCheckDecode {{
+ {
+ MipsStaticInst *i = new %(class_name)s(machInst);
+
+ //if (RD == 0) {
+ // 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, 'MipsStaticInst', CodeBlock(code),
+ opt_args)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
diff --git a/arch/mips/isa/formats/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..6884d4fa8
--- /dev/null
+++ b/arch/mips/isa/formats/trap.isa
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////////////
+//
+// 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, *flags) {{
+ code = 'bool cond;\n' + code;
+ 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/unimp.isa b/arch/mips/isa/formats/unimp.isa
new file mode 100644
index 000000000..adbd5b5b1
--- /dev/null
+++ b/arch/mips/isa/formats/unimp.isa
@@ -0,0 +1,165 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+ /**
+ * Static instruction class for unimplemented instructions that
+ * cause simulator termination. Note that these are recognized
+ * (legal) instructions that the simulator does not support; the
+ * 'Unknown' class is used for unrecognized/illegal instructions.
+ * This is a leaf class.
+ */
+ class FailUnimplemented : public MipsStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for unimplemented instructions that cause a warning
+ * to be printed (but do not terminate simulation). This
+ * implementation is a little screwy in that it will print a
+ * warning for each instance of a particular unimplemented machine
+ * instruction, not just for each unimplemented opcode. Should
+ * probably make the 'warned' flag a static member of the derived
+ * class.
+ */
+ class WarnUnimplemented : public MipsStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s", mnemonic);
+#else
+ return csprintf("%-10s (unimplemented)", mnemonic);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
+ return 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 MipsStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(MachInst _machInst)
+ : MipsStaticInst("unknown", _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa
new file mode 100644
index 000000000..4601b3684
--- /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 UnimplementedOpcodeFault;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
+
diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa
new file mode 100644
index 000000000..db4bf204a
--- /dev/null
+++ b/arch/mips/isa/formats/util.isa
@@ -0,0 +1,148 @@
+// -*- mode:c++ -*-
+
+let {{
+def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code = '', base_class = 'Memory',
+ decode_template = BasicDecode, exec_template_base = ''):
+ # Make sure flags are in lists (convert to lists if not).
+ mem_flags = makeList(mem_flags)
+ inst_flags = makeList(inst_flags)
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+
+ # generate code block objects
+ ea_cblk = CodeBlock(ea_code)
+ memacc_cblk = CodeBlock(memacc_code)
+ postacc_cblk = CodeBlock(postacc_code)
+
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # generate InstObjParams for EAComp object
+ ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+
+ # generate InstObjParams for MemAcc object
+ memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+ # in the split execution model, the MemAcc portion is responsible
+ # for the post-access code.
+ memacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for InitiateAcc, CompleteAcc object
+ # The code used depends on the template being used
+ if (exec_template_base == 'Load'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(memacc_code + postacc_code)
+ elif (exec_template_base == 'Store'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(postacc_code)
+ else:
+ initiateacc_cblk = ''
+ completeacc_cblk = ''
+
+ initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk,
+ inst_flags)
+
+ completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk,
+ inst_flags)
+
+ if (exec_template_base == 'Load'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+ elif (exec_template_base == 'Store'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for unified execution
+ cblk = CodeBlock(ea_code + memacc_code + postacc_code)
+ iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
+
+ iop.ea_constructor = ea_cblk.constructor
+ iop.ea_code = ea_cblk.code
+ iop.memacc_constructor = memacc_cblk.constructor
+ iop.memacc_code = memacc_cblk.code
+ iop.postacc_code = postacc_cblk.code
+
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
+
+ # select templates
+ memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
+ fullExecTemplate = eval(exec_template_base + 'Execute')
+ initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
+ completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
+
+ # (header_output, decoder_output, decode_block, exec_output)
+ return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + memAccExecTemplate.subst(memacc_iop)
+ + fullExecTemplate.subst(iop)
+ + initiateAccTemplate.subst(initiateacc_iop)
+ + completeAccTemplate.subst(completeacc_iop))
+}};
+
+
+output exec {{
+
+using namespace MipsISA;
+
+
+ /// CLEAR ALL CPU INST/EXE HAZARDS
+ inline void
+ clear_exe_inst_hazards()
+ {
+ //CODE HERE
+ }
+
+
+ /// 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 (!Mips34k::ICSR_FPE(xc->readIpr(MipsISA::IPR_ICSR, fault))) {
+ fault = FloatEnableFault;
+ }
+ return fault;
+ }
+#else
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#endif
+
+ double convert_and_round(float w, int x, int y, int z)
+ {
+ double temp = .34000;
+
+ return temp;
+ }
+
+ enum FPTypes{
+ FP_SINGLE,
+ FP_DOUBLE,
+ FP_LONG,
+ FP_PS_LO,
+ FP_PS_HI,
+ FP_WORD,
+ RND_NEAREST,
+ RND_ZERO,
+ RND_UP,
+ RND_DOWN
+ };
+}};
+
+
diff --git a/arch/mips/isa/includes.isa b/arch/mips/isa/includes.isa
new file mode 100644
index 000000000..da919be00
--- /dev/null
+++ b/arch/mips/isa/includes.isa
@@ -0,0 +1,39 @@
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "cpu/static_inst.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..13870337b
--- /dev/null
+++ b/arch/mips/isa/operands.isa
@@ -0,0 +1,33 @@
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sh' : ('signed int', 16),
+ 'uh' : ('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),
+ 'r31': ('IntReg', 'uw','R31','IsInteger', 4),
+ 'R0': ('IntReg', 'uw','R0', 'IsInteger', 5),
+
+ 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
+
+ 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1),
+ 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2),
+ 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3),
+ 'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3),
+
+ 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+
+ 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4),
+ 'NNPC':('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4)
+}};
diff --git a/arch/mips/isa_traits.cc b/arch/mips/isa_traits.cc
new file mode 100644
index 000000000..d01fa6bd4
--- /dev/null
+++ b/arch/mips/isa_traits.cc
@@ -0,0 +1,403 @@
+/*
+ * 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 "config/full_system.hh"
+#include "cpu/static_inst.hh"
+#include "sim/serialize.hh"
+
+using namespace MipsISA;
+
+
+//Function now Obsolete in current state.
+//If anyting this should return the correct miscreg index
+//but that is handled implicitly with enums anyway
+void
+MipsISA::getMiscRegIdx(int reg_name,int &idx, int &sel)
+{
+ switch(reg_name)
+ {
+ case Index: idx = 0; sel = 0; break; //0-0 Index into the TLB array
+ case MVPControl: idx = 0; sel = 1; break; //0-1 Per-processor register containing global
+ case MVPConf0: idx = 0; sel = 2; break; //0-2 Per-processor register containing global
+ case MVPConf1: idx = 0; sel = 3; break; //0-3 Per-processor register containing global
+ case Random: idx = 1; sel = 3; break; //1-0 Randomly generated index into the TLB array
+ case VPEControl: idx = 1; sel = 1; break; //1-1 Per-VPE register containing relatively volatile
+ //thread configuration data
+ case VPEConf0: idx = 1; sel = 2; break; //1-2 Per-VPE multi-thread configuration
+ //information
+ case VPEConf1: idx = 1; sel = 3; break; //1-3 Per-VPE multi-thread configuration
+ //information
+ case YQMask: idx = 1; sel = 4; break; //Per-VPE register defining which YIELD
+ //qualifier bits may be used without generating
+ //an exception
+ case VPESchedule: idx = 1; sel = 5; break;
+ case VPEScheFBack: idx = 1; sel = 6; break;
+ case VPEOpt: idx = 1; sel = 7; break;
+ case EntryLo0: idx = 1; sel = 5; break;
+ case TCStatus: idx = 1; sel = 5; break;
+ case TCBind: idx = 1; sel = 5; break;
+ case TCRestart: idx = 1; sel = 5; break;
+ case TCHalt: idx = 1; sel = 5; break;
+ case TCContext: idx = 1; sel = 5; break;
+ case TCSchedule: idx = 1; sel = 5; break;
+ case TCScheFBack: panic("Accessing Unimplemented CP0 Register"); break;
+ case EntryLo1: panic("Accessing Unimplemented CP0 Register"); break;
+ case Context: panic("Accessing Unimplemented CP0 Register"); break;
+ case ContextConfig: panic("Accessing Unimplemented CP0 Register"); break;
+ //case PageMask: panic("Accessing Unimplemented CP0 Register"); break;
+ case PageGrain: panic("Accessing Unimplemented CP0 Register"); break;
+ case Wired: panic("Accessing Unimplemented CP0 Register"); break;
+ case SRSConf0: panic("Accessing Unimplemented CP0 Register"); break;
+ case SRSConf1: panic("Accessing Unimplemented CP0 Register"); break;
+ case SRSConf2: panic("Accessing Unimplemented CP0 Register"); break;
+ case SRSConf3: panic("Accessing Unimplemented CP0 Register"); break;
+ case SRSConf4: panic("Accessing Unimplemented CP0 Register"); break;
+ case BadVAddr: panic("Accessing Unimplemented CP0 Register"); break;
+ case Count: panic("Accessing Unimplemented CP0 Register"); break;
+ case EntryHi: panic("Accessing Unimplemented CP0 Register"); break;
+ case Compare: panic("Accessing Unimplemented CP0 Register"); break;
+ case Status: idx = 12; sel = 0; break; //12-0 Processor status and control
+ case IntCtl: idx = 12; sel = 1; break; //12-1 Interrupt system status and control
+ case SRSCtl: idx = 12; sel = 2; break; //12-2 Shadow register set status and control
+ case SRSMap: idx = 12; sel = 3; break; //12-3 Shadow set IPL mapping
+ case Cause: idx = 13; sel = 0; break; //13-0 Cause of last general exception
+ case EPC: idx = 14; sel = 0; break; //14-0 Program counter at last exception
+ case PrId: idx = 15; sel = 0; break; //15-0 Processor identification and revision
+ case EBase: idx = 15; sel = 1; break; //15-1 Exception vector base register
+ case Config: panic("Accessing Unimplemented CP0 Register"); break;
+ case Config1: panic("Accessing Unimplemented CP0 Register"); break;
+ case Config2: panic("Accessing Unimplemented CP0 Register"); break;
+ case Config3: panic("Accessing Unimplemented CP0 Register"); break;
+ case LLAddr: panic("Accessing Unimplemented CP0 Register"); break;
+ case WatchLo: panic("Accessing Unimplemented CP0 Register"); break;
+ case WatchHi: panic("Accessing Unimplemented CP0 Register"); break;
+ case Debug: panic("Accessing Unimplemented CP0 Register"); break;
+ case TraceControl1: panic("Accessing Unimplemented CP0 Register"); break;
+ case TraceControl2: panic("Accessing Unimplemented CP0 Register"); break;
+ case UserTraceData: panic("Accessing Unimplemented CP0 Register"); break;
+ case TraceBPC: panic("Accessing Unimplemented CP0 Register"); break;
+ case DEPC: panic("Accessing Unimplemented CP0 Register"); break;
+ case PerfCnt: panic("Accessing Unimplemented CP0 Register"); break;
+ case ErrCtl: panic("Accessing Unimplemented CP0 Register"); break;
+ case CacheErr0: panic("Accessing Unimplemented CP0 Register"); break;
+ case CacheErr1: panic("Accessing Unimplemented CP0 Register"); break;
+ case CacheErr2: panic("Accessing Unimplemented CP0 Register"); break;
+ case CacheErr3: panic("Accessing Unimplemented CP0 Register"); break;
+ case TagLo: panic("Accessing Unimplemented CP0 Register"); break;
+ case DataLo: panic("Accessing Unimplemented CP0 Register"); break;
+ case TagHi: panic("Accessing Unimplemented CP0 Register"); break;
+ case DataHi: panic("Accessing Unimplemented CP0 Register"); break;
+ case ErrorEPC: panic("Accessing Unimplemented CP0 Register"); break;
+
+ default:
+ panic("Accessing Unimplemented Misc. Register");
+ }
+}
+
+void RegFile::coldReset()
+{
+ //CP0 Random Reg:
+ //Randomly generated index into the TLB array
+ miscRegs[Random] = 0x0000003f;
+
+ //CP0 Wired Reg.
+ miscRegs[Wired] = 0x0000000;
+
+ //CP0 HWRENA
+ miscRegs[HWRena] = 0x0000000;
+
+ //CP0 Status Reg.
+ miscRegs[Status] = 0x0400004;
+
+ //CP0 INTCNTL
+ miscRegs[IntCtl] = 0xfc00000;
+
+ //CP0 SRSCNTL
+ miscRegs[SRSCtl] = 0x0c00000;
+
+ //CP0 SRSMAP
+ miscRegs[SRSMap] = 0x0000000;
+
+ //CP0 Cause
+ miscRegs[Cause] = 0x0000000;
+
+ //CP0 Processor ID
+ miscRegs[PrId] = 0x0019300;
+
+ //CP0 EBASE
+ miscRegs[EBase] = 0x8000000;
+
+ //CP0 Config Reg.
+ miscRegs[Config] = 0x80040482;
+
+ //CP0 Config 1 Reg.
+ miscRegs[Config1] = 0xfee3719e;
+
+ //CP0 Config 2 Reg.
+ miscRegs[Config2] = 0x8000000;
+
+ //CP0 Config 3 Reg.
+ miscRegs[Config3] = 0x0000020;
+
+ //CP0 Config 7 Reg.
+ miscRegs[Config7] = 0x0000000;
+
+ //CP0 Debug
+ miscRegs[Debug] = 0x0201800;
+
+ //CP0 PERFCNTL1
+ miscRegs[PerfCnt0] = 0x0000000;
+
+ //CP0 PERFCNTL2
+ miscRegs[PerfCnt1] = 0x0000000;
+
+}
+
+void RegFile::createCP0Regs()
+{
+//Resize Coprocessor Register Banks to
+// the number specified in MIPS32K VOL.III
+// Chapter 8
+ /*
+ //Cop-0 Regs. Bank 0: Index,
+ miscRegs[0].resize(4);
+
+ //Cop-0 Regs. Bank 1:
+ miscRegs[1].resize(8);
+
+ //Cop-0 Regs. Bank 2:
+ miscRegs[2].resize(8);
+
+ //Cop-0 Regs. Bank 3:
+ miscRegs[3].resize(1);
+
+ //Cop-0 Regs. Bank 4:
+ miscRegs[4].resize(2);
+
+ //Cop-0 Regs. Bank 5:
+ miscRegs[5].resize(2);
+
+ //Cop-0 Regs. Bank 6:
+ miscRegs[6].resize(6);
+
+ //Cop-0 Regs. Bank 7:
+ miscRegs[7].resize(1);
+
+ //Cop-0 Regs. Bank 8:
+ miscRegs[8].resize(1);
+
+ //Cop-0 Regs. Bank 9:
+ miscRegs[9].resize(1);
+
+ //Cop-0 Regs. Bank 10:
+ miscRegs[10].resize(1);
+
+ //Cop-0 Regs. Bank 11:
+ miscRegs[11].resize(1);
+
+ //Cop-0 Regs. Bank 12:
+ miscRegs[12].resize(4);
+
+ //Cop-0 Regs. Bank 13:
+ miscRegs[13].resize(1);
+
+ //Cop-0 Regs. Bank 14:
+ miscRegs[14].resize(1);
+
+ //Cop-0 Regs. Bank 15:
+ miscRegs[15].resize(2);
+
+ //Cop-0 Regs. Bank 16:
+ miscRegs[16].resize(4);
+
+ //Cop-0 Regs. Bank 17:
+ miscRegs[17].resize(1);
+
+ //Cop-0 Regs. Bank 18:
+ miscRegs[18].resize(8);
+
+ //Cop-0 Regs. Bank 19:
+ miscRegs[19].resize(8);
+
+ //Cop-0 Regs. Bank 20:
+ miscRegs[20].resize(1);
+
+ //Cop-0 Regs. Bank 21:
+ //miscRegs[21].resize(1);
+ //Reserved for future extensions
+
+ //Cop-0 Regs. Bank 22:
+ //miscRegs[22].resize(4);
+ //Available for implementation dependent use
+
+ //Cop-0 Regs. Bank 23:
+ miscRegs[23].resize(5);
+
+ //Cop-0 Regs. Bank 24:
+ miscRegs[24].resize(1);
+
+ //Cop-0 Regs. Bank 25:
+ miscRegs[25].resize(8);
+
+ //Cop-0 Regs. Bank 26:
+ miscRegs[26].resize(1);
+
+ //Cop-0 Regs. Bank 27:
+ miscRegs[27].resize(4);
+
+ //Cop-0 Regs. Bank 28:
+ miscRegs[28].resize(8);
+
+ //Cop-0 Regs. Bank 29:
+ miscRegs[29].resize(8);
+
+ //Cop-0 Regs. Bank 30:
+ miscRegs[30].resize(1);
+
+ //Cop-0 Regs. Bank 31:
+ miscRegs[31].resize(1);*/
+
+}
+
+
+const Addr MipsISA::PageShift = 13;
+const Addr MipsISA::PageBytes = ULL(1) << PageShift;
+const Addr MipsISA::PageMask = ~(PageBytes - 1);
+const Addr MipsISA::PageOffset = PageBytes - 1;
+
+#if FULL_SYSTEM
+
+////////////////////////////////////////////////////////////////////////
+//
+// Translation stuff
+//
+
+const Addr MipsISA::PteShift = 3;
+const Addr MipsISA::NPtePageShift = PageShift - PteShift;
+const Addr MipsISA::NPtePage = ULL(1) << NPtePageShift;
+const Addr MipsISA::PteMask = NPtePage - 1;
+
+// User Virtual
+const Addr MipsISA::USegBase = ULL(0x0);
+const Addr MipsISA::USegEnd = ULL(0x000003ffffffffff);
+
+// Kernel Direct Mapped
+const Addr MipsISA::K0SegBase = ULL(0xfffffc0000000000);
+const Addr MipsISA::K0SegEnd = ULL(0xfffffdffffffffff);
+
+// Kernel Virtual
+const Addr MipsISA::K1SegBase = ULL(0xfffffe0000000000);
+const Addr MipsISA::K1SegEnd = ULL(0xffffffffffffffff);
+
+#endif
+
+// Mips UNOP (sll r0,r0,r0)
+const MachInst MipsISA::NoopMachInst = 0x00000000;
+
+static inline Addr
+TruncPage(Addr addr)
+{ return addr & ~(MipsISA::PageBytes - 1); }
+
+static inline Addr
+RoundPage(Addr addr)
+{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); }
+
+void
+RegFile::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY(intRegFile, NumIntRegs);
+ SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ //SERIALIZE_SCALAR(miscRegs.fpcr);
+ //SERIALIZE_SCALAR(miscRegs.uniq);
+ //SERIALIZE_SCALAR(miscRegs.lock_flag);
+ //SERIALIZE_SCALAR(miscRegs.lock_addr);
+ SERIALIZE_SCALAR(pc);
+ SERIALIZE_SCALAR(npc);
+ SERIALIZE_SCALAR(nnpc);
+#if FULL_SYSTEM
+ SERIALIZE_ARRAY(palregs, NumIntRegs);
+ SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
+ SERIALIZE_SCALAR(intrflag);
+ SERIALIZE_SCALAR(pal_shadow);
+#endif
+}
+
+
+void
+RegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(intRegFile, NumIntRegs);
+ UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ //UNSERIALIZE_SCALAR(miscRegs.fpcr);
+ //UNSERIALIZE_SCALAR(miscRegs.uniq);
+ //UNSERIALIZE_SCALAR(miscRegs.lock_flag);
+ //UNSERIALIZE_SCALAR(miscRegs.lock_addr);
+ UNSERIALIZE_SCALAR(pc);
+ UNSERIALIZE_SCALAR(npc);
+ UNSERIALIZE_SCALAR(nnpc);
+#if FULL_SYSTEM
+ UNSERIALIZE_ARRAY(palregs, NumIntRegs);
+ UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
+ UNSERIALIZE_SCALAR(intrflag);
+ UNSERIALIZE_SCALAR(pal_shadow);
+#endif
+}
+
+
+#if FULL_SYSTEM
+void
+PTE::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(tag);
+ SERIALIZE_SCALAR(ppn);
+ SERIALIZE_SCALAR(xre);
+ SERIALIZE_SCALAR(xwe);
+ SERIALIZE_SCALAR(asn);
+ SERIALIZE_SCALAR(asma);
+ SERIALIZE_SCALAR(fonr);
+ SERIALIZE_SCALAR(fonw);
+ SERIALIZE_SCALAR(valid);
+}
+
+
+void
+PTE::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(tag);
+ UNSERIALIZE_SCALAR(ppn);
+ UNSERIALIZE_SCALAR(xre);
+ UNSERIALIZE_SCALAR(xwe);
+ UNSERIALIZE_SCALAR(asn);
+ UNSERIALIZE_SCALAR(asma);
+ UNSERIALIZE_SCALAR(fonr);
+ UNSERIALIZE_SCALAR(fonw);
+ UNSERIALIZE_SCALAR(valid);
+}
+
+#endif //FULL_SYSTEM
diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh
new file mode 100644
index 000000000..1dfa0dc7a
--- /dev/null
+++ b/arch/mips/isa_traits.hh
@@ -0,0 +1,546 @@
+/*
+ * 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__
+
+//#include "arch/mips/misc_regfile.hh"
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "sim/host.hh"
+#include "sim/faults.hh"
+
+#include <vector>
+
+class FastCPU;
+class FullCPU;
+class Checkpoint;
+
+namespace LittleEndianGuest {};
+using namespace LittleEndianGuest;
+
+#define TARGET_MIPS
+
+class StaticInst;
+class StaticInstPtr;
+
+namespace MIPS34K {
+int DTB_ASN_ASN(uint64_t reg);
+int ITB_ASN_ASN(uint64_t reg);
+};
+
+namespace MipsISA
+{
+ typedef uint32_t MachInst;
+// typedef uint64_t Addr;
+ typedef uint8_t RegIndex;
+
+ enum {
+ MemoryEnd = 0xffffffffffffffffULL,
+
+ NumIntRegs = 32,
+ NumFloatRegs = 32,
+ NumMiscRegs = 258, //account for hi,lo regs
+
+ MaxRegsOfAnyType = 32,
+ // Static instruction parameters
+ MaxInstSrcRegs = 3,
+ MaxInstDestRegs = 2,
+
+ // semantically meaningful register indices
+ ZeroReg = 0, // architecturally meaningful
+ // the rest of these depend on the ABI
+ StackPointerReg = 30,
+ GlobalPointerReg = 29,
+ ProcedureValueReg = 27,
+ ReturnAddressReg = 26,
+ ReturnValueReg = 0,
+ FramePointerReg = 15,
+ ArgumentReg0 = 16,
+ ArgumentReg1 = 17,
+ ArgumentReg2 = 18,
+ ArgumentReg3 = 19,
+ ArgumentReg4 = 20,
+ ArgumentReg5 = 21,
+
+ LogVMPageSize = 13, // 8K bytes
+ VMPageSize = (1 << LogVMPageSize),
+
+ BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned
+
+ WordBytes = 4,
+ HalfwordBytes = 2,
+ ByteBytes = 1,
+ DepNA = 0,
+ };
+
+ // These enumerate all the registers for dependence tracking.
+ enum DependenceTags {
+ // 0..31 are the integer regs 0..31
+ // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
+ FP_Base_DepTag = 32,
+ Ctrl_Base_DepTag = 64,
+ Fpcr_DepTag = 64, // floating point control register
+ Uniq_DepTag = 65,
+ IPR_Base_DepTag = 66,
+ MiscReg_DepTag = 67
+ };
+
+ typedef uint64_t IntReg;
+ typedef IntReg IntRegFile[NumIntRegs];
+
+ // floating point register file entry type
+ typedef union {
+ uint64_t q;
+ double d;
+ } FloatReg;
+
+ typedef union {
+ uint64_t q[NumFloatRegs]; // integer qword view
+ double d[NumFloatRegs]; // double-precision floating point view
+ } FloatRegFile;
+
+ // cop-0/cop-1 system control register file
+ typedef uint64_t MiscReg;
+//typedef MiscReg MiscRegFile[NumMiscRegs];
+ class MiscRegFile {
+ public:
+ MiscReg
+ protected:
+ uint64_t fpcr; // floating point condition codes
+ uint64_t uniq; // process-unique register
+ bool lock_flag; // lock flag for LL/SC
+ Addr lock_addr; // lock address for LL/SC
+
+ MiscReg miscRegFile[NumMiscRegs];
+
+ public:
+ //These functions should be removed once the simplescalar cpu model
+ //has been replaced.
+ int getInstAsid();
+ int getDataAsid();
+
+ MiscReg readReg(int misc_reg)
+ { return miscRegFile[misc_reg]; }
+
+ MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc)
+ { return miscRegFile[misc_reg];}
+
+ Fault setReg(int misc_reg, const MiscReg &val)
+ { miscRegFile[misc_reg] = val; return NoFault; }
+
+ Fault setRegWithEffect(int misc_reg, const MiscReg &val,
+ ExecContext *xc)
+ { miscRegFile[misc_reg] = val; return NoFault; }
+
+#if FULL_SYSTEM
+ void clearIprs() { };
+
+ protected:
+ InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
+
+ private:
+ MiscReg readIpr(int idx, Fault &fault, ExecContext *xc) { }
+
+ Fault setIpr(int idx, uint64_t val, ExecContext *xc) { }
+#endif
+ friend class RegFile;
+ };
+
+ enum MiscRegTags {
+ //Coprocessor 0 Registers
+ //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8
+ //(Register Number-Register Select) Summary of Register
+ //------------------------------------------------------
+ Index = 0, //0-0 Index into the TLB array
+
+ MVPControl = 1, //0-1 Per-processor register containing global
+ //MIPS® MT configuration data
+
+ MVPConf0 = 2, //0-2 Per-processor register containing global
+ //MIPS® MT configuration data
+
+ MVPConf1 = 3, //0-3 Per-processor register containing global
+ //MIPS® MT configuration data
+
+ Random = 8, //1-0 Randomly generated index into the TLB array
+
+ VPEControl = 9, //1-1 Per-VPE register containing relatively volatile
+ //thread configuration data
+
+ VPEConf0 = 10, //1-2 Per-VPE multi-thread configuration
+ //information
+
+
+ VPEConf1 = 11, //1-2 Per-VPE multi-thread configuration
+ //information
+
+ YQMask = 12, //Per-VPE register defining which YIELD
+ //qualifier bits may be used without generating
+ //an exception
+
+ VPESchedule = 13,
+ VPEScheFBack = 14,
+ VPEOpt = 15,
+ EntryLo0 = 16, // Bank 3: 16 - 23
+ TCStatus = 17,
+ TCBind = 18,
+ TCRestart = 19,
+ TCHalt = 20,
+ TCContext = 21,
+ TCSchedule = 22,
+ TCScheFBack = 23,
+
+ EntryLo1 = 24,// Bank 4: 24 - 31
+
+ Context = 32, // Bank 5: 32 - 39
+ ContextConfig = 33,
+
+ //PageMask = 40, //Bank 6: 40 - 47
+ PageGrain = 41,
+
+ Wired = 48, //Bank 7:48 - 55
+ SRSConf0 = 49,
+ SRSConf1 = 50,
+ SRSConf2 = 51,
+ SRSConf3 = 52,
+ SRSConf4 = 53,
+ BadVAddr = 54,
+
+ HWRena = 56,//Bank 8:56 - 63
+
+ Count = 64, //Bank 9:64 - 71
+
+ EntryHi = 72,//Bank 10:72 - 79
+
+ Compare = 80,//Bank 11:80 - 87
+
+ Status = 88,//Bank 12:88 - 96 //12-0 Processor status and control
+ IntCtl = 89, //12-1 Interrupt system status and control
+ SRSCtl = 90, //12-2 Shadow register set status and control
+ SRSMap = 91, //12-3 Shadow set IPL mapping
+
+ Cause = 97,//97-104 //13-0 Cause of last general exception
+
+ EPC = 105,//105-112 //14-0 Program counter at last exception
+
+ PRId = 113//113-120, //15-0 Processor identification and revision
+ EBase = 114, //15-1 Exception vector base register
+
+ Config = 121,//Bank 16: 121-128
+ Config1 = 122,
+ Config2 = 123,
+ Config3 = 124,
+ Config6 = 127,
+ Config7 = 128,
+
+
+ LLAddr = 129,//Bank 17: 129-136
+
+ WatchLo0 = 137,//Bank 18: 137-144
+ WatchLo1 = 138,
+ WatchLo2 = 139,
+ WatchLo3 = 140,
+ WatchLo4 = 141,
+ WatchLo5 = 142,
+ WatchLo6 = 143,
+ WatchLo7 = 144,
+
+ WatchHi0 = 145,//Bank 19: 145-152
+ WatchHi1 = 146,
+ WatchHi2 = 147,
+ WatchHi3 = 148,
+ WatchHi4 = 149,
+ WatchHi5 = 150,
+ WatchHi6 = 151,
+ WatchHi7 = 152,
+
+ XCContext64 = 153,//Bank 20: 153-160
+
+ //Bank 21: 161-168
+
+ //Bank 22: 169-176
+
+ Debug = 177, //Bank 23: 177-184
+ TraceControl1 = 178,
+ TraceControl2 = 179,
+ UserTraceData = 180,
+ TraceBPC = 181,
+
+ DEPC = 185,//Bank 24: 185-192
+
+ PerfCnt0 = 193,//Bank 25: 193 - 200
+ PerfCnt1 = 194,
+ PerfCnt2 = 195,
+ PerfCnt3 = 196,
+ PerfCnt4 = 197,
+ PerfCnt5 = 198,
+ PerfCnt6 = 199,
+ PerfCnt7 = 200,
+
+ ErrCtl = 201, //Bank 26: 201 - 208
+
+ CacheErr0 = 209, //Bank 27: 209 - 216
+ CacheErr1 = 210,
+ CacheErr2 = 211,
+ CacheErr3 = 212,
+
+ TagLo0 = 217,//Bank 28: 217 - 224
+ DataLo1 = 218,
+ TagLo2 = 219,
+ DataLo3 = 220,
+ TagLo4 = 221,
+ DataLo5 = 222,
+ TagLo6 = 223,
+ DataLo7 = 234,
+
+ TagHi0 = 233,//Bank 29: 233 - 240
+ DataHi1 = 234,
+ TagHi2 = 235,
+ DataHi3 = 236,
+ TagHi4 = 237,
+ DataHi5 = 238,
+ TagHi6 = 239,
+ DataHi7 = 240,
+
+
+ ErrorEPC = 249,//Bank 30: 241 - 248
+
+ DESAVE = 257,//Bank 31: 249-256
+
+ //More Misc. Regs
+ Hi,
+ Lo,
+ FCSR,
+ FPCR,
+
+ //Alpha Regs, but here now, for
+ //compiling sake
+ UNIQ,
+ LockAddr,
+ LockFlag
+ };
+
+extern const Addr PageShift;
+extern const Addr PageBytes;
+extern const Addr PageMask;
+extern const Addr PageOffset;
+
+#if FULL_SYSTEM
+
+ typedef uint64_t InternalProcReg;
+
+#include "arch/mips/isa_fullsys_traits.hh"
+
+#else
+ enum {
+ NumInternalProcRegs = 0
+ };
+#endif
+
+ enum {
+ TotalNumRegs =
+ NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
+ };
+
+ enum {
+ TotalDataRegs = NumIntRegs + NumFloatRegs
+ };
+
+ typedef union {
+ IntReg intreg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ struct RegFile {
+ IntRegFile intRegFile; // (signed) integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegs; // control register file
+
+
+ Addr pc; // program counter
+ Addr npc; // next-cycle program counter
+ Addr nnpc; // next-next-cycle program counter
+ // used to implement branch delay slot
+ // not real register
+
+ MiscReg hi; // MIPS HI Register
+ MiscReg lo; // MIPS LO Register
+
+
+#if FULL_SYSTEM
+ IntReg palregs[NumIntRegs]; // PAL shadow registers
+ InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
+ int intrflag; // interrupt flag
+ bool pal_shadow; // using pal_shadow registers
+ inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
+ inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
+#endif // FULL_SYSTEM
+
+ //void initCP0Regs();
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ void createCP0Regs();
+ void coldReset();
+ };
+
+ StaticInstPtr decodeInst(MachInst);
+
+ // return a no-op instruction... used for instruction fetch faults
+ extern const MachInst NoopMachInst;
+
+ enum annotes {
+ ANNOTE_NONE = 0,
+ // An impossible number for instruction annotations
+ ITOUCH_ANNOTE = 0xffffffff,
+ };
+
+ void getMiscRegIdx(int reg_name,int &idx, int &sel);
+
+
+ static inline bool isCallerSaveIntegerRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
+ }
+
+ static inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return (reg >= 9 && reg <= 15);
+ }
+
+ static inline bool isCallerSaveFloatRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ static inline bool isCalleeSaveFloatRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ static inline Addr alignAddress(const Addr &addr,
+ unsigned int nbytes) {
+ return (addr & ~(nbytes - 1));
+ }
+
+ // 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);
+ }
+
+ static inline MachInst makeRegisterCopy(int dest, int src) {
+ panic("makeRegisterCopy not implemented");
+ return 0;
+ }
+
+ // Machine operations
+
+ void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
+ int regnum);
+
+ void restoreMachineReg(RegFile &regs, const AnyReg &reg,
+ int regnum);
+
+#if 0
+ static void serializeSpecialRegs(const Serializable::Proxy &proxy,
+ const RegFile &regs);
+
+ static void unserializeSpecialRegs(const IniFile *db,
+ const std::string &category,
+ ConfigNode *node,
+ RegFile &regs);
+#endif
+
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param xc The execution context.
+ */
+ template <class XC>
+ void zeroRegisters(XC *xc);
+
+ const Addr MaxAddr = (Addr)-1;
+};
+
+#if !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
+
+
+#if FULL_SYSTEM
+//typedef TheISA::InternalProcReg InternalProcReg;
+//const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
+//const int NumInterruptLevels = TheISA::NumInterruptLevels;
+
+#include "arch/mips/mips34k.hh"
+#endif
+
+#endif // __ARCH_MIPS_ISA_TRAITS_HH__
diff --git a/arch/alpha/alpha_linux_process.cc b/arch/mips/linux_process.cc
index 16816e901..1d4f62350 100644
--- a/arch/alpha/alpha_linux_process.cc
+++ b/arch/mips/linux_process.cc
@@ -26,457 +26,97 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h> // for host open() flags
-#include <string.h> // for memset()
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include "arch/mips/common_syscall_emul.hh"
+#include "arch/mips/linux_process.hh"
+#include "arch/mips/isa_traits.hh"
-#include "cpu/base.hh"
+#include "base/trace.hh"
#include "cpu/exec_context.hh"
-#include "mem/translating_port.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/host.hh"
-#include "sim/process.hh"
-#include "sim/sim_events.hh"
+#include "kern/linux/linux.hh"
+#include "mem/functional/functional.hh"
-#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "sim/process.hh"
#include "sim/syscall_emul.hh"
-#include "sim/root.hh" // for curTick & ticksPerSecond
-
-#include "arch/alpha/alpha_linux_process.hh"
-
-#include "base/trace.hh"
using namespace std;
+using namespace MipsISA;
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Linux
-/// syscall interface.
-///
-class Linux {
-
- public:
-
- //@{
- /// Basic Linux types.
- typedef uint64_t size_t;
- typedef uint64_t off_t;
- typedef int64_t time_t;
- typedef uint32_t uid_t;
- typedef uint32_t gid_t;
- //@}
-
- //@{
- /// open(2) flag values.
- static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
- static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
- static const int TGT_O_RDWR = 00000002; //!< O_RDWR
- static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK
- static const int TGT_O_APPEND = 00000010; //!< O_APPEND
- static const int TGT_O_CREAT = 00001000; //!< O_CREAT
- static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC
- static const int TGT_O_EXCL = 00004000; //!< O_EXCL
- static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY
- static const int TGT_O_SYNC = 00040000; //!< O_SYNC
- static const int TGT_O_DRD = 00100000; //!< O_DRD
- static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO
- static const int TGT_O_CACHE = 00400000; //!< O_CACHE
- static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC
- static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC
- //@}
-
- /// This table maps the target open() flags to the corresponding
- /// host open() flags.
- static OpenFlagTransTable openFlagTable[];
-
- /// Number of entries in openFlagTable[].
- static const int NUM_OPEN_FLAGS;
-
- /// Stat buffer. Note that we can't call it 'stat' since that
- /// gets #defined to something else on some systems.
- struct tgt_stat {
- uint32_t st_dev; //!< device
- uint32_t st_ino; //!< inode
- uint32_t st_mode; //!< mode
- uint32_t st_nlink; //!< link count
- uint32_t st_uid; //!< owner's user ID
- uint32_t st_gid; //!< owner's group ID
- uint32_t st_rdev; //!< device number
- int32_t _pad1; //!< for alignment
- int64_t st_size; //!< file size in bytes
- uint64_t st_atimeX; //!< time of last access
- uint64_t st_mtimeX; //!< time of last modification
- uint64_t st_ctimeX; //!< time of last status change
- uint32_t st_blksize; //!< optimal I/O block size
- int32_t st_blocks; //!< number of blocks allocated
- uint32_t st_flags; //!< flags
- uint32_t st_gen; //!< unknown
- };
-
- // same for stat64
- struct tgt_stat64 {
- uint64_t st_dev;
- uint64_t st_ino;
- uint64_t st_rdev;
- int64_t st_size;
- uint64_t st_blocks;
-
- uint32_t st_mode;
- uint32_t st_uid;
- uint32_t st_gid;
- uint32_t st_blksize;
- uint32_t st_nlink;
- uint32_t __pad0;
-
- uint64_t tgt_st_atime;
- uint64_t st_atime_nsec;
- uint64_t tgt_st_mtime;
- uint64_t st_mtime_nsec;
- uint64_t tgt_st_ctime;
- uint64_t st_ctime_nsec;
- int64_t __unused[3];
- };
-
- /// Length of strings in struct utsname (plus 1 for null char).
- static const int _SYS_NMLN = 65;
-
- /// Interface struct for uname().
- struct utsname {
- char sysname[_SYS_NMLN]; //!< System name.
- char nodename[_SYS_NMLN]; //!< Node name.
- char release[_SYS_NMLN]; //!< OS release.
- char version[_SYS_NMLN]; //!< OS version.
- char machine[_SYS_NMLN]; //!< Machine type.
- };
-
-
- //@{
- /// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- static const unsigned TIOCGETS = 0x402c7413;
- static const unsigned TIOCGETA = 0x40127417;
- //@}
-
- /// Resource enumeration for getrlimit().
- enum rlimit_resources {
- 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
- };
-
- /// Limit struct for getrlimit/setrlimit.
- struct rlimit {
- uint64_t rlim_cur; //!< soft limit
- uint64_t rlim_max; //!< hard limit
- };
-
-
- /// For mmap().
- static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
- /// For gettimeofday().
- struct timeval {
- int64_t tv_sec; //!< seconds
- int64_t tv_usec; //!< microseconds
- };
-
- // For writev/readv
- struct tgt_iovec {
- uint64_t iov_base; // void *
- uint64_t iov_len;
- };
-
- //@{
- /// For getrusage().
- static const int RUSAGE_SELF = 0;
- static const int RUSAGE_CHILDREN = -1;
- static const int RUSAGE_BOTH = -2;
- //@}
-
- /// For getrusage().
- struct rusage {
- struct timeval ru_utime; //!< user time used
- struct timeval ru_stime; //!< system time used
- int64_t ru_maxrss; //!< max rss
- int64_t ru_ixrss; //!< integral shared memory size
- int64_t ru_idrss; //!< integral unshared data "
- int64_t ru_isrss; //!< integral unshared stack "
- int64_t ru_minflt; //!< page reclaims - total vmfaults
- int64_t ru_majflt; //!< page faults
- int64_t ru_nswap; //!< swaps
- int64_t ru_inblock; //!< block input operations
- int64_t ru_oublock; //!< block output operations
- int64_t ru_msgsnd; //!< messages sent
- int64_t ru_msgrcv; //!< messages received
- int64_t ru_nsignals; //!< signals received
- int64_t ru_nvcsw; //!< voluntary context switches
- int64_t ru_nivcsw; //!< involuntary "
- };
-
- /// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
- static void
- copyOutStatBuf(TranslatingPort *memPort, Addr addr, struct 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.copyOut(memPort);
- }
-
- // Same for stat64
- static void
- copyOutStat64Buf(TranslatingPort *memPort, Addr addr, struct stat64 *host)
- {
- TypedBufferArg<Linux::tgt_stat64> tgt(addr);
-
- // XXX byteswaps
- tgt->st_dev = 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;
-#else
- tgt->st_atime_nsec = 0;
- tgt->st_mtime_nsec = 0;
- tgt->st_ctime_nsec = 0;
-#endif
- tgt.copyOut(memPort);
- }
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Target uname() handler.
- static SyscallReturn
- unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "Linux");
- strcpy(name->nodename, hostname);
- strcpy(name->release, "2.4.20");
- strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
- strcpy(name->machine, "alpha");
-
- name.copyOut(xc->port);
- return 0;
- }
-
- /// Target osf_getsysyinfo() handler. Even though this call is
- /// borrowed from Tru64, the subcases that get used appear to be
- /// different in practice from those used by Tru64 processes.
- static SyscallReturn
- osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 45: { // GSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- *fpcr = 0;
- fpcr.copyOut(xc->port);
- return 0;
- }
-
- default:
- cerr << "osf_getsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
- }
-
- /// Target osf_setsysinfo() handler.
- static SyscallReturn
- osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 14: { // SSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- fpcr.copyIn(xc->port);
- DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
- " setting FPCR to 0x%x\n", *(uint64_t*)fpcr);
- return 0;
- }
-
- default:
- cerr << "osf_setsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
- }
-
- /// Target fnctl() handler.
- static SyscallReturn
- fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int fd = xc->getSyscallArg(0);
-
- if (fd < 0 || process->sim_fd(fd) < 0)
- return -EBADF;
-
- int cmd = xc->getSyscallArg(1);
- switch (cmd) {
- case 0: // F_DUPFD
- // if we really wanted to support this, we'd need to do it
- // in the target fd space.
- warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
- return -EMFILE;
-
- case 1: // F_GETFD (get close-on-exec flag)
- case 2: // F_SETFD (set close-on-exec flag)
- return 0;
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
- case 3: // F_GETFL (get file flags)
- case 4: // F_SETFL (set file flags)
- // not sure if this is totally valid, but we'll pass it through
- // to the underlying OS
- warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
- return fcntl(process->sim_fd(fd), cmd);
- // return 0;
+ strcpy(name->sysname, "Linux");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "2.4.20");
+ strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+ strcpy(name->machine, "mips");
- case 7: // F_GETLK (get lock)
- case 8: // F_SETLK (set lock)
- case 9: // F_SETLKW (set lock and wait)
- // don't mess with file locking... just act like it's OK
- warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
- return 0;
+ name.copyOut(xc->mem);
+ return 0;
+}
- default:
- warn("Unknown fcntl command %d\n", cmd);
- return 0;
- }
+/// Target osf_getsysyinfo() handler. Even though this call is
+/// borrowed from Tru64, the subcases that get used appear to be
+/// different in practice from those used by Tru64 processes.
+static SyscallReturn
+osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ // unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case 45: { // GSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+ // I don't think this exactly matches the HW FPCR
+ *fpcr = 0;
+ fpcr.copyOut(xc->mem);
+ return 0;
+ }
+
+ default:
+ cerr << "osf_getsysinfo: unknown op " << op << endl;
+ abort();
+ break;
}
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- /// Number of syscalls in syscallDescs[].
- static const int Num_Syscall_Descs;
-
- /// Max supported syscall number.
- static const int Max_Syscall_Desc;
-
- /// Do the specified syscall. Just looks the call number up in
- /// the table and invokes the appropriate handler.
- static void
- doSyscall(int callnum, Process *process, ExecContext *xc)
- {
- if (callnum < 0 || callnum > Max_Syscall_Desc) {
- fatal("Syscall %d out of range", callnum);
- }
-
- SyscallDesc *desc = &syscallDescs[callnum];
+ return 1;
+}
- desc->doSyscall(callnum, process, xc);
+/// Target osf_setsysinfo() handler.
+static SyscallReturn
+osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ // unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case 14: { // SSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+ // I don't think this exactly matches the HW FPCR
+ fpcr.copyIn(xc->mem);
+ DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
+ " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
+ return 0;
+ }
+
+ default:
+ cerr << "osf_setsysinfo: unknown op " << op << endl;
+ abort();
+ break;
}
-}; // class Linux
-
-
-// open(2) flags translation table
-OpenFlagTransTable Linux::openFlagTable[] = {
-#ifdef _MSC_VER
- { Linux::TGT_O_RDONLY, _O_RDONLY },
- { Linux::TGT_O_WRONLY, _O_WRONLY },
- { Linux::TGT_O_RDWR, _O_RDWR },
- { Linux::TGT_O_APPEND, _O_APPEND },
- { Linux::TGT_O_CREAT, _O_CREAT },
- { Linux::TGT_O_TRUNC, _O_TRUNC },
- { Linux::TGT_O_EXCL, _O_EXCL },
-#ifdef _O_NONBLOCK
- { Linux::TGT_O_NONBLOCK, _O_NONBLOCK },
-#endif
-#ifdef _O_NOCTTY
- { Linux::TGT_O_NOCTTY, _O_NOCTTY },
-#endif
-#ifdef _O_SYNC
- { Linux::TGT_O_SYNC, _O_SYNC },
-#endif
-#else /* !_MSC_VER */
- { Linux::TGT_O_RDONLY, O_RDONLY },
- { Linux::TGT_O_WRONLY, O_WRONLY },
- { Linux::TGT_O_RDWR, O_RDWR },
- { Linux::TGT_O_APPEND, O_APPEND },
- { Linux::TGT_O_CREAT, O_CREAT },
- { Linux::TGT_O_TRUNC, O_TRUNC },
- { Linux::TGT_O_EXCL, O_EXCL },
- { Linux::TGT_O_NONBLOCK, O_NONBLOCK },
- { Linux::TGT_O_NOCTTY, O_NOCTTY },
-#ifdef O_SYNC
- { Linux::TGT_O_SYNC, O_SYNC },
-#endif
-#endif /* _MSC_VER */
-};
-const int Linux::NUM_OPEN_FLAGS =
- (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0]));
+ return 1;
+}
-const char *Linux::hostname = "m5.eecs.umich.edu";
-SyscallDesc Linux::syscallDescs[] = {
+SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 0 */ SyscallDesc("osf_syscall", unimplementedFunc),
/* 1 */ SyscallDesc("exit", exitFunc),
/* 2 */ SyscallDesc("fork", unimplementedFunc),
@@ -924,32 +564,25 @@ SyscallDesc Linux::syscallDescs[] = {
/* 441 */ SyscallDesc("keyctl", unimplementedFunc)
};
-const int Linux::Num_Syscall_Descs =
- sizeof(Linux::syscallDescs) / sizeof(SyscallDesc);
-
-const int Linux::Max_Syscall_Desc = Linux::Num_Syscall_Descs - 1;
-
-
-void
-AlphaLinuxProcess::syscall(ExecContext *xc)
-{
- num_syscalls++;
-
- int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
-
- Linux::doSyscall(callnum, this, xc);
-}
-
-
-AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
+MipsLinuxProcess::MipsLinuxProcess(const std::string &name,
ObjectFile *objFile,
- System *system,
int stdin_fd,
int stdout_fd,
int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp)
- : LiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd,
- argv, envp)
+ : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
+{
+ init_regs->intRegFile[0] = 0;
+}
+
+
+
+SyscallDesc*
+MipsLinuxProcess::getDesc(int callnum)
{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
}
diff --git a/arch/mips/linux_process.hh b/arch/mips/linux_process.hh
new file mode 100644
index 000000000..5408a6c44
--- /dev/null
+++ b/arch/mips/linux_process.hh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef __MIPS_LINUX_PROCESS_HH__
+#define __MIPS_LINUX_PROCESS_HH__
+
+#include "sim/process.hh"
+
+
+/// A process with emulated Mips/Linux syscalls.
+class MipsLinuxProcess : public LiveProcess
+{
+ public:
+ /// Constructor.
+ MipsLinuxProcess(const std::string &name,
+ ObjectFile *objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
+
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
+};
+
+
+#endif // __MIPS_LINUX_PROCESS_HH__
diff --git a/arch/mips/process.cc b/arch/mips/process.cc
new file mode 100644
index 000000000..6de44fe9f
--- /dev/null
+++ b/arch/mips/process.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#include "arch/mips/process.hh"
+
+namespace MipsISA
+{
+
+LiveProcess *
+createProcess(const string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ vector<string> &argv, vector<string> &envp)
+{
+ LiveProcess * process = NULL;
+ if (objFile->getArch() != ObjectFile::MIPS)
+ fatal("Object file does not match architecture.");
+ switch (objFile->getOpSys()) {
+ case ObjectFile::Linux:
+ process = new MipsLinuxProcess(nm, objFile,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+ return process;
+}
+
+} // namespace MipsISA
+
diff --git a/arch/mips/process.hh b/arch/mips/process.hh
new file mode 100644
index 000000000..ab4323107
--- /dev/null
+++ b/arch/mips/process.hh
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef __MIPS_PROCESS_HH__
+#define __MIPS_PROCESS_HH__
+
+#include "arch/mips/linux_process.hh"
+#include "base/loader/object_file.hh"
+
+namespace MipsISA
+{
+
+LiveProcess *
+createProcess(const string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ vector<string> &argv, vector<string> &envp);
+
+} // namespace MipsISA
+
+#endif // __MIPS_PROCESS_HH__
diff --git a/arch/mips/stacktrace.hh b/arch/mips/stacktrace.hh
new file mode 100644
index 000000000..1d8d97a79
--- /dev/null
+++ b/arch/mips/stacktrace.hh
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_STACKTRACE_HH__
+#define __ARCH_ALPHA_STACKTRACE_HH__
+
+#include "base/trace.hh"
+#include "cpu/static_inst.hh"
+
+class ExecContext;
+class StackTrace;
+
+class ProcessInfo
+{
+ private:
+ ExecContext *xc;
+
+ int thread_info_size;
+ int task_struct_size;
+ int task_off;
+ int pid_off;
+ int name_off;
+
+ public:
+ ProcessInfo(ExecContext *_xc);
+
+ Addr task(Addr ksp) const;
+ int pid(Addr ksp) const;
+ std::string name(Addr ksp) const;
+};
+
+class StackTrace
+{
+ protected:
+ typedef TheISA::MachInst MachInst;
+ private:
+ ExecContext *xc;
+ std::vector<Addr> stack;
+
+ private:
+ bool isEntry(Addr addr);
+ bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
+ bool decodeSave(MachInst inst, int &reg, int &disp);
+ bool decodeStack(MachInst inst, int &disp);
+
+ void trace(ExecContext *xc, bool is_call);
+
+ public:
+ StackTrace();
+ StackTrace(ExecContext *xc, StaticInstPtr inst);
+ ~StackTrace();
+
+ void clear()
+ {
+ xc = 0;
+ stack.clear();
+ }
+
+ bool valid() const { return xc != NULL; }
+ bool trace(ExecContext *xc, StaticInstPtr inst);
+
+ public:
+ const std::vector<Addr> &getstack() const { return stack; }
+
+ static const int user = 1;
+ static const int console = 2;
+ static const int unknown = 3;
+
+#if TRACING_ON
+ private:
+ void dump();
+
+ public:
+ void dprintf() { if (DTRACE(Stack)) dump(); }
+#else
+ public:
+ void dprintf() {}
+#endif
+};
+
+inline bool
+StackTrace::trace(ExecContext *xc, StaticInstPtr inst)
+{
+ if (!inst->isCall() && !inst->isReturn())
+ return false;
+
+ if (valid())
+ clear();
+
+ trace(xc, !inst->isReturn());
+ return true;
+}
+
+#endif // __ARCH_ALPHA_STACKTRACE_HH__
diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript
new file mode 100644
index 000000000..edff5821e
--- /dev/null
+++ b/arch/sparc/SConscript
@@ -0,0 +1,82 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ tlb.cc
+ arguments.cc
+ ev5.cc
+ osfpal.cc
+ stacktrace.cc
+ vtophys.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ common_syscall_emul.cc
+ linux_process.cc
+ process.cc
+ ''')
+
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/arch/sparc/faults.cc b/arch/sparc/faults.cc
new file mode 100644
index 000000000..b48fc600b
--- /dev/null
+++ b/arch/sparc/faults.cc
@@ -0,0 +1,248 @@
+/*
+ * 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/sparc/faults.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "base/trace.hh"
+
+namespace SparcISA
+{
+
+FaultName InternalProcessorError::_name = "intprocerr";
+TrapType InternalProcessorError::_trapType = 0x029;
+FaultPriority InternalProcessorError::_priority = 4;
+FaultStat InternalProcessorError::_count;
+
+FaultName MemAddressNotAligned::_name = "unalign";
+TrapType MemAddressNotAligned::_trapType = 0x034;
+FaultPriority MemAddressNotAligned::_priority = 10;
+FaultStat MemAddressNotAligned::_count;
+
+FaultName PowerOnReset::_name = "pow_reset";
+TrapType PowerOnReset::_trapType = 0x001;
+FaultPriority PowerOnReset::_priority = 0;
+FaultStat PowerOnReset::_count;
+
+FaultName WatchDogReset::_name = "watch_dog_reset";
+TrapType WatchDogReset::_trapType = 0x002;
+FaultPriority WatchDogReset::_priority = 1;
+FaultStat WatchDogReset::_count;
+
+FaultName ExternallyInitiatedReset::_name = "extern_reset";
+TrapType ExternallyInitiatedReset::_trapType = 0x003;
+FaultPriority ExternallyInitiatedReset::_priority = 1;
+FaultStat ExternallyInitiatedReset::_count;
+
+FaultName SoftwareInitiatedReset::_name = "software_reset";
+TrapType SoftwareInitiatedReset::_trapType = 0x004;
+FaultPriority SoftwareInitiatedReset::_priority = 1;
+FaultStat SoftwareInitiatedReset::_count;
+
+FaultName REDStateException::_name = "red_counte";
+TrapType REDStateException::_trapType = 0x005;
+FaultPriority REDStateException::_priority = 1;
+FaultStat REDStateException::_count;
+
+FaultName InstructionAccessException::_name = "inst_access";
+TrapType InstructionAccessException::_trapType = 0x008;
+FaultPriority InstructionAccessException::_priority = 5;
+FaultStat InstructionAccessException::_count;
+
+FaultName InstructionAccessMMUMiss::_name = "inst_mmu";
+TrapType InstructionAccessMMUMiss::_trapType = 0x009;
+FaultPriority InstructionAccessMMUMiss::_priority = 2;
+FaultStat InstructionAccessMMUMiss::_count;
+
+FaultName InstructionAccessError::_name = "inst_error";
+TrapType InstructionAccessError::_trapType = 0x00A;
+FaultPriority InstructionAccessError::_priority = 3;
+FaultStat InstructionAccessError::_count;
+
+FaultName IllegalInstruction::_name = "illegal_inst";
+TrapType IllegalInstruction::_trapType = 0x010;
+FaultPriority IllegalInstruction::_priority = 7;
+FaultStat IllegalInstruction::_count;
+
+FaultName PrivelegedOpcode::_name = "priv_opcode";
+TrapType PrivelegedOpcode::_trapType = 0x011;
+FaultPriority PrivelegedOpcode::_priority = 6;
+FaultStat PrivelegedOpcode::_count;
+
+FaultName UnimplementedLDD::_name = "unimp_ldd";
+TrapType UnimplementedLDD::_trapType = 0x012;
+FaultPriority UnimplementedLDD::_priority = 6;
+FaultStat UnimplementedLDD::_count;
+
+FaultName UnimplementedSTD::_name = "unimp_std";
+TrapType UnimplementedSTD::_trapType = 0x013;
+FaultPriority UnimplementedSTD::_priority = 6;
+FaultStat UnimplementedSTD::_count;
+
+FaultName FpDisabled::_name = "fp_disabled";
+TrapType FpDisabled::_trapType = 0x020;
+FaultPriority FpDisabled::_priority = 8;
+FaultStat FpDisabled::_count;
+
+FaultName FpExceptionIEEE754::_name = "fp_754";
+TrapType FpExceptionIEEE754::_trapType = 0x021;
+FaultPriority FpExceptionIEEE754::_priority = 11;
+FaultStat FpExceptionIEEE754::_count;
+
+FaultName FpExceptionOther::_name = "fp_other";
+TrapType FpExceptionOther::_trapType = 0x022;
+FaultPriority FpExceptionOther::_priority = 11;
+FaultStat FpExceptionOther::_count;
+
+FaultName TagOverflow::_name = "tag_overflow";
+TrapType TagOverflow::_trapType = 0x023;
+FaultPriority TagOverflow::_priority = 14;
+FaultStat TagOverflow::_count;
+
+FaultName DivisionByZero::_name = "div_by_zero";
+TrapType DivisionByZero::_trapType = 0x028;
+FaultPriority DivisionByZero::_priority = 15;
+FaultStat DivisionByZero::_count;
+
+FaultName DataAccessException::_name = "data_access";
+TrapType DataAccessException::_trapType = 0x030;
+FaultPriority DataAccessException::_priority = 12;
+FaultStat DataAccessException::_count;
+
+FaultName DataAccessMMUMiss::_name = "data_mmu";
+TrapType DataAccessMMUMiss::_trapType = 0x031;
+FaultPriority DataAccessMMUMiss::_priority = 12;
+FaultStat DataAccessMMUMiss::_count;
+
+FaultName DataAccessError::_name = "data_error";
+TrapType DataAccessError::_trapType = 0x032;
+FaultPriority DataAccessError::_priority = 12;
+FaultStat DataAccessError::_count;
+
+FaultName DataAccessProtection::_name = "data_protection";
+TrapType DataAccessProtection::_trapType = 0x033;
+FaultPriority DataAccessProtection::_priority = 12;
+FaultStat DataAccessProtection::_count;
+
+FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf";
+TrapType LDDFMemAddressNotAligned::_trapType = 0x035;
+FaultPriority LDDFMemAddressNotAligned::_priority = 10;
+FaultStat LDDFMemAddressNotAligned::_count;
+
+FaultName STDFMemAddressNotAligned::_name = "unalign_stdf";
+TrapType STDFMemAddressNotAligned::_trapType = 0x036;
+FaultPriority STDFMemAddressNotAligned::_priority = 10;
+FaultStat STDFMemAddressNotAligned::_count;
+
+FaultName PrivelegedAction::_name = "priv_action";
+TrapType PrivelegedAction::_trapType = 0x037;
+FaultPriority PrivelegedAction::_priority = 11;
+FaultStat PrivelegedAction::_count;
+
+FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
+TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
+FaultPriority LDQFMemAddressNotAligned::_priority = 10;
+FaultStat LDQFMemAddressNotAligned::_count;
+
+FaultName STQFMemAddressNotAligned::_name = "unalign_stqf";
+TrapType STQFMemAddressNotAligned::_trapType = 0x039;
+FaultPriority STQFMemAddressNotAligned::_priority = 10;
+FaultStat STQFMemAddressNotAligned::_count;
+
+FaultName AsyncDataError::_name = "async_data";
+TrapType AsyncDataError::_trapType = 0x040;
+FaultPriority AsyncDataError::_priority = 2;
+FaultStat AsyncDataError::_count;
+
+//The enumerated faults
+
+FaultName CleanWindow::_name = "clean_win";
+TrapType CleanWindow::_baseTrapType = 0x024;
+FaultPriority CleanWindow::_priority = 10;
+FaultStat CleanWindow::_count;
+
+FaultName InterruptLevelN::_name = "interrupt_n";
+TrapType InterruptLevelN::_baseTrapType = 0x041;
+FaultStat InterruptLevelN::_count;
+
+FaultName SpillNNormal::_name = "spill_n_normal";
+TrapType SpillNNormal::_baseTrapType = 0x080;
+FaultPriority SpillNNormal::_priority = 9;
+FaultStat SpillNNormal::_count;
+
+FaultName SpillNOther::_name = "spill_n_other";
+TrapType SpillNOther::_baseTrapType = 0x0A0;
+FaultPriority SpillNOther::_priority = 9;
+FaultStat SpillNOther::_count;
+
+FaultName FillNNormal::_name = "fill_n_normal";
+TrapType FillNNormal::_baseTrapType = 0x0C0;
+FaultPriority FillNNormal::_priority = 9;
+FaultStat FillNNormal::_count;
+
+FaultName FillNOther::_name = "fill_n_other";
+TrapType FillNOther::_baseTrapType = 0x0E0;
+FaultPriority FillNOther::_priority = 9;
+FaultStat FillNOther::_count;
+
+FaultName TrapInstruction::_name = "trap_inst_n";
+TrapType TrapInstruction::_baseTrapType = 0x100;
+FaultPriority TrapInstruction::_priority = 16;
+FaultStat TrapInstruction::_count;
+
+
+
+#if FULL_SYSTEM
+
+void SparcFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ countStat()++;
+
+ //Use the SPARC trap state machine
+ /*// exception restart address
+ if (setRestartAddress() || !xc->inPalMode())
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, xc->regs.pc);
+
+ if (skipFaultingInstruction()) {
+ // traps... skip faulting instruction.
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
+ xc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
+ }
+
+ if (!xc->inPalMode())
+ AlphaISA::swap_palshadow(&(xc->regs), true);
+
+ xc->regs.pc = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
+ xc->regs.npc = xc->regs.pc + sizeof(MachInst);*/
+}
+
+#endif
+
+} // namespace SparcISA
+
diff --git a/arch/sparc/faults.hh b/arch/sparc/faults.hh
new file mode 100644
index 000000000..318b1ad5a
--- /dev/null
+++ b/arch/sparc/faults.hh
@@ -0,0 +1,587 @@
+/*
+ * 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 __ALPHA_FAULTS_HH__
+#define __ALPHA_FAULTS_HH__
+
+#include "sim/faults.hh"
+
+// The design of the "name" and "vect" functions is in sim/faults.hh
+
+namespace SparcISA
+{
+
+typedef const uint32_t TrapType;
+typedef const uint32_t FaultPriority;
+
+class SparcFault : public FaultBase
+{
+ public:
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+ virtual TrapType trapType() = 0;
+ virtual FaultPriority priority() = 0;
+ virtual FaultStat & countStat() = 0;
+};
+
+class InternalProcessorError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+ bool isMachineCheckFault() {return true;}
+};
+
+class MemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+ bool isAlignmentFault() {return true;}
+};
+
+static inline Fault genMachineCheckFault()
+{
+ return new InternalProcessorError;
+}
+
+static inline Fault genAlignmentFault()
+{
+ return new MemAddressNotAligned;
+}
+
+class PowerOnReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class WatchDogReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ExternallyInitiatedReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class SoftwareInitiatedReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class REDStateException : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InstructionAccessException : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InstructionAccessMMUMiss : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InstructionAccessError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class IllegalInstruction : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PrivelegedOpcode : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedLDD : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedSTD : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FpDisabled : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FpExceptionIEEE754 : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FpExceptionOther : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class TagOverflow : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DivisionByZero : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessException : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessMMUMiss : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessProtection : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class LDDFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class STDFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PrivelegedAction : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class LDQFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class STQFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class AsyncDataError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class EnumeratedFault : public SparcFault
+{
+ protected:
+ uint32_t _n;
+ virtual TrapType baseTrapType() = 0;
+ public:
+ EnumeratedFault(uint32_t n) : SparcFault() {_n = n;}
+ TrapType trapType() {return baseTrapType() + _n;}
+};
+
+class CleanWindow : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ CleanWindow(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InterruptLevelN : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ InterruptLevelN(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return 32 - _n;}
+ FaultStat & countStat() {return _count;}
+};
+
+class SpillNNormal : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ SpillNNormal(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class SpillNOther : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ SpillNOther(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FillNNormal : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ FillNNormal(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FillNOther : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ FillNOther(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class TrapInstruction : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ TrapInstruction(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+} // SparcISA namespace
+
+#endif // __FAULTS_HH__
diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa
new file mode 100644
index 000000000..992504369
--- /dev/null
+++ b/arch/sparc/isa/base.isa
@@ -0,0 +1,129 @@
+////////////////////////////////////////////////////////////////////
+//
+// Base class for sparc instructions, and some support functions
+//
+
+output header {{
+
+ struct condCodes
+ {
+ uint8_t c:1;
+ uint8_t v:1;
+ uint8_t z:1;
+ uint8_t n:1;
+ }
+
+ enum condTest
+ {
+ Always=0x8,
+ Never=0x0,
+ NotEqual=0x9,
+ Equal=0x1,
+ Greater=0xA,
+ LessOrEqual=0x2,
+ GreaterOrEqual=0xB,
+ Less=0x3,
+ GreaterUnsigned=0xC,
+ LessOrEqualUnsigned=0x4,
+ CarryClear=0xD,
+ CarrySet=0x5,
+ Positive=0xE,
+ Negative=0x6,
+ OverflowClear=0xF,
+ OverflowSet=0x7
+ }
+
+ /**
+ * Base class for all SPARC static instructions.
+ */
+ class SparcStaticInst : public StaticInst
+ {
+ protected:
+ // Constructor.
+ SparcStaticInst(const char *mnem,
+ MachInst _machInst, OpClass __opClass)
+ : StaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ bool passesCondition(condCodes codes, condTest 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(condCodes codes, condTest condition)
+ {
+ switch(condition)
+ {
+ case Always:
+ return true;
+ case Never:
+ return false;
+ case NotEqual:
+ return !codes.z;
+ case Equal:
+ return codes.z;
+ case Greater:
+ return !(codes.z | (codes.n ^ codes.v));
+ case LessOrEqual:
+ return codes.z | (codes.n ^ codes.v);
+ case GreaterOrEqual:
+ return !(codes.n ^ codes.v);
+ case Less:
+ return (codes.n ^ codes.v);
+ case GreaterUnsigned:
+ return !(codes.c | codes.z);
+ case LessOrEqualUnsigned:
+ return (codes.c | codes.z);
+ case CarryClear:
+ return !codes.c;
+ case CarrySet:
+ return codes.c;
+ case Positive:
+ return !codes.n;
+ case Negative:
+ return codes.n;
+ case OverflowClear:
+ return !codes.v;
+ case OverflowSet:
+ 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..eb458211b
--- /dev/null
+++ b/arch/sparc/isa/decoder.isa
@@ -0,0 +1,662 @@
+////////////////////////////////////////////////////////////////////
+//
+// The actual decoder specification
+//
+
+decode OP default Trap::unknown({{IllegalInstruction}}) {
+
+ 0x0: decode OP2 {
+ 0x0: Trap::illtrap({{illegal_instruction}}); //ILLTRAP
+ 0x1: Branch::bpcc({{
+ switch((CC12 << 1) | CC02)
+ {
+ case 1:
+ case 3:
+ fault = new IllegalInstruction;
+ 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:
+ fault = new IllegalInstruction;
+ 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
+ //SETHI (or NOP if rd == 0 and imm == 0)
+ 0x4: IntegerOp::sethi({{Rd = (IMM22 << 10) & 0xFFFFFC00;}});
+ 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_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ Rd = Rs1.sdw + val2;
+ }});//ADD
+ 0x01: and({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw & val2;
+ }});//AND
+ 0x02: or({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw | val2;
+ }});//OR
+ 0x03: xor({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw ^ val2;
+ }});//XOR
+ 0x04: sub({{
+ int64_t val2 = ~((uint64_t)(I ? SIMM13.sdw : Rs2.udw))+1;
+ Rd = Rs1.sdw + val2;
+ }});//SUB
+ 0x05: andn({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw & ~val2;
+ }});//ANDN
+ 0x06: orn({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = Rs1.udw | ~val2;
+ }});//ORN
+ 0x07: xnor({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ Rd = ~(Rs1.udw ^ val2);
+ }});//XNOR
+ 0x08: addc({{
+ int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
+ Rd = Rs1.sdw + val2 + carryin;
+ }});//ADDC
+ 0x09: mulx({{
+ int64_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 * val2;
+ }});//MULX
+ 0x0A: umul({{
+ uint64_t 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_t 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_t val2 = ~((int64_t)(I ? SIMM13.sdw : Rs2.sdw))+1;
+ int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
+ Rd.sdw = Rs1.sdw + val2 + carryin;
+ }});//SUBC
+ 0x0D: udivx({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
+ if(val2 == 0) throw division_by_zero;
+ Rd.udw = Rs1.udw / val2;
+ }});//UDIVX
+ 0x0E: udiv({{
+ uint32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>);
+ if(val2 == 0)
+ fault = new DivisionByZero;
+ resTemp = (uint64_t)((xc->regs.MiscRegs.yFields.value << 32)
+ | Rs1.udw<31:0>) / val2;
+ int32_t overflow = (resTemp<63:32> != 0);
+ if(overflow)
+ rd.udw = resTemp = 0xFFFFFFFF;
+ else
+ rd.udw = resTemp;
+ }}); //UDIV
+ 0x0F: sdiv({{
+ int32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>);
+ if(val2 == 0)
+ fault = new DivisionByZero;
+
+ Rd.sdw = (int64_t)((xc->regs.MiscRegs.yFields.value << 32) |
+ Rs1.sdw<31:0>) / val2;
+ resTemp = Rd.sdw;
+ int32_t overflow = (resTemp<63:31> != 0);
+ int32_t 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_t 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_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 & val2;}},
+ {{0}},{{0}},{{0}},{{0}});//ANDcc
+ 0x12: orcc({{
+ int64_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 | val2;}},
+ {{0}},{{0}},{{0}},{{0}});//ORcc
+ 0x13: xorcc({{
+ int64_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 ^ val2;}},
+ {{0}},{{0}},{{0}},{{0}});//XORcc
+ 0x14: subcc({{
+ int64_t resTemp, val2 = (int64_t)(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_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 & ~val2;}},
+ {{0}},{{0}},{{0}},{{0}});//ANDNcc
+ 0x16: orncc({{
+ int64_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = Rs1 | ~val2;}},
+ {{0}},{{0}},{{0}},{{0}});//ORNcc
+ 0x17: xnorcc({{
+ int64_t val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = ~(Rs1 ^ val2);}},
+ {{0}},{{0}},{{0}},{{0}});//XNORcc
+ 0x18: addccc({{
+ int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ int64_t 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_t 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_t 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_t resTemp, val2 = (int64_t)(I ? SIMM13.sdw : Rs2);
+ int64_t 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_t 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_t resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>);
+ if(val2 == 0) throw division_by_zero;
+ resTemp = (uint64_t)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.udw<31:0>) / val2;
+ int32_t overflow = (resTemp<63:32> != 0);
+ if(overflow) rd.udw = resTemp = 0xFFFFFFFF;
+ else rd.udw = resTemp;}},
+ {{0}},
+ {{overflow}},
+ {{0}},
+ {{0}}
+ );//UDIVcc
+ 0x1F: sdivcc({{
+ int32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>);
+ if(val2 == 0) throw division_by_zero;
+ Rd.sdw = resTemp = (int64_t)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.sdw<31:0>) / val2;
+ int32_t overflow = (resTemp<63:31> != 0);
+ int32_t 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_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ int32_t 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_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ int32_t 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_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ int32_t 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_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
+ Rd = resTemp = Rs1 + val2;
+ int32_t 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_t resTemp, multiplicand = (I ? SIMM13.sdw : Rs2);
+ int32_t multiplier = Rs1<31:0>;
+ int32_t 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_t 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_t count = 0, val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ uint8_t 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_t 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_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.y = Rs1 ^ val2;
+ }});//WRY
+ 0x2: wrccr({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.ccr = Rs1 ^ val2;
+ }});//WRCCR
+ 0x3: wrasi({{
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.asi = Rs1 ^ val2;
+ }});//WRASI
+ 0x6: wrfprs({{
+ uint64_t 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_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x1: wrprtnpc({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x2: wrprtstate({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x3: wrprtt({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
+ }});
+ 0x4: wrprtick({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tick = Rs1 ^ val2;
+ }});
+ 0x5: wrprtba({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tba = Rs1 ^ val2;
+ }});
+ 0x6: wrprpstate({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.pstate = Rs1 ^ val2;
+ }});
+ 0x7: wrprtl({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.tl = Rs1 ^ val2;
+ }});
+ 0x8: wrprpil({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.pil = Rs1 ^ val2;
+ }});
+ 0x9: wrprcwp({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.cwp = Rs1 ^ val2;
+ }});
+ 0xA: wrprcansave({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.cansave = Rs1 ^ val2;
+ }});
+ 0xB: wrprcanrestore({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.canrestore = Rs1 ^ val2;
+ }});
+ 0xC: wrprcleanwin({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.cleanwin = Rs1 ^ val2;
+ }});
+ 0xD: wrprotherwin({{checkPriv
+ uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
+ xc->regs.MiscRegs.otherwin = Rs1 ^ val2;
+ }});
+ 0xE: wrprwstate({{checkPriv
+ uint64_t 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_t 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_t 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_t 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_t 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_t val = Mem.uw;
+ if(Rs2.uw == val)
+ Mem.uw = Rd.uw;
+ Rd.uw = val;
+ }}); //CASA
+ 0x3D: Noop::prefetcha({{ }}); //PREFETCHA
+ 0x3E: Cas::casxa(
+ {{uint64_t 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..73df7617d
--- /dev/null
+++ b/arch/sparc/isa/formats/basic.isa
@@ -0,0 +1,68 @@
+
+// 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, '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..80101de1b
--- /dev/null
+++ b/arch/sparc/isa/formats/branch.isa
@@ -0,0 +1,62 @@
+////////////////////////////////////////////////////////////////////
+//
+// 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 "Branch instruction\n";
+ }
+}};
+
+def template BranchExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ //Attempt to execute the instruction
+ Fault fault = NoFault;
+ checkPriv;
+
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return 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..5a9e09896
--- /dev/null
+++ b/arch/sparc/isa/formats/integerop.isa
@@ -0,0 +1,112 @@
+////////////////////////////////////////////////////////////////////
+//
+// 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 "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..d72de47d0
--- /dev/null
+++ b/arch/sparc/isa/formats/mem.isa
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////
+//
+// 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 "Memory instruction\n";
+ }
+}};
+
+def template MemExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ %(op_decl)s;
+ %(op_rd)s;
+ ea_code
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return 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..fa4047f06
--- /dev/null
+++ b/arch/sparc/isa/formats/noop.isa
@@ -0,0 +1,50 @@
+////////////////////////////////////////////////////////////////////
+//
+// Noop instruction
+//
+
+output header {{
+ /**
+ * Noop class.
+ */
+ 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 "Noop\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 NoFault;
+ }
+}};
+
+// 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..ff3aadf72
--- /dev/null
+++ b/arch/sparc/isa/formats/trap.isa
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////
+//
+// 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 "Trap instruction\n";
+ }
+}};
+
+def template TrapExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ //TODO: set up a software fault and return it.
+ return NoFault;
+ }
+}};
+
+// 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..a99018b49
--- /dev/null
+++ b/arch/sparc/isa/includes.isa
@@ -0,0 +1,43 @@
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "cpu/static_inst.hh"
+#include "arch/sparc/faults.hh"
+#include "mem/mem_req.hh" // some constructors use MemReq flags
+#include "arch/sparc/isa_traits.hh"
+}};
+
+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
+
+using namespace SparcISA;
+}};
+
+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..64f5abd08
--- /dev/null
+++ b/arch/sparc/isa/operands.isa
@@ -0,0 +1,31 @@
+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),
+ 'R0': ('IntReg', 'udw', '0', None, 1),
+ 'R16': ('IntReg', 'udw', '16', None, 1)
+}};
diff --git a/arch/sparc/isa_traits.hh b/arch/sparc/isa_traits.hh
new file mode 100644
index 000000000..bd3c35beb
--- /dev/null
+++ b/arch/sparc/isa_traits.hh
@@ -0,0 +1,527 @@
+/*
+ * 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__
+
+#include "arch/sparc/faults.hh"
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "sim/host.hh"
+
+//This makes sure the big endian versions of certain functions are used.
+namespace BigEndianGuest {}
+using namespace BigEndianGuest;
+
+class ExecContext;
+class FastCPU;
+//class FullCPU;
+class Checkpoint;
+
+#define TARGET_SPARC
+
+class StaticInst;
+class StaticInstPtr;
+
+//namespace EV5
+//{
+// int DTB_ASN_ASN(uint64_t reg);
+// int ITB_ASN_ASN(uint64_t reg);
+//}
+
+namespace SparcISA
+{
+ typedef uint32_t MachInst;
+ typedef uint64_t ExtMachInst;
+ typedef uint8_t RegIndex;
+
+ const int NumFloatRegs = 32;
+ const int NumMiscRegs = 32;
+
+ const int // Maximum trap level
+ const int MaxTL = 4;
+ const int
+ const int // semantically meaningful register indices
+ const int ZeroReg = 0; // architecturally meaningful
+ const int // the rest of these depend on the ABI
+ const int StackPointerReg = 14;
+ const int ReturnAddressReg = 31; // post call, precall is 15
+ const int ReturnValueReg = 8; // Post return, 24 is pre-return.
+ const int FramePointerReg = 30;
+ const int ArgumentReg0 = 8;
+ const int ArgumentReg1 = 9;
+ const int ArgumentReg2 = 10;
+ const int ArgumentReg3 = 11;
+ const int ArgumentReg4 = 12;
+ const int ArgumentReg5 = 13;
+ // Some OS syscall sue a second register (o1) to return a second value
+ const int SyscallPseudoReturnReg = ArgumentReg1;
+
+
+ //8K. This value is implmentation specific; and should probably
+ //be somewhere else.
+ const int LogVMPageSize = 13;
+ const int VMPageSize = (1 << LogVMPageSize);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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 serialize(std::ostream & os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ typedef float float32_t;
+ typedef double float64_t;
+ //FIXME This actually usually refers to a 10 byte float, rather than a
+ //16 byte float as required. This data type may have to be emulated.
+ typedef long double float128_t;
+
+ class FloatRegFile
+ {
+ private:
+ //By using the largest data type, we ensure everything
+ //is aligned correctly in memory
+ union
+ {
+ float128_t rawRegs[16];
+ uint64_t regDump[32];
+ };
+ class QuadRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ QuadRegs(FloatRegFile * p) : parent(p) {;}
+ float128_t & 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) {;}
+ float64_t & 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 ((float64_t *)parent->rawRegs)[index];
+ }
+ };
+ class SingleRegs
+ {
+ private:
+ FloatRegFile * parent;
+ public:
+ SingleRegs(FloatRegFile * p) : parent(p) {;}
+ float32_t & operator [] (RegIndex index)
+ {
+ //Only 32 single floats should be accessed
+ index &= 0x1F;
+ return ((float32_t *)parent->rawRegs)[index];
+ }
+ };
+ public:
+ void serialize(std::ostream & os);
+
+ void unserialize(Checkpoint * cp, std::string & section);
+
+ 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
+ {
+ private:
+ 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
+ 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;
+ };
+ 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;
+ };
+ } 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
+ uint64_t :2; // Reserved bits
+ uint64_t pstate:10; // Process State
+ 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
+ uint64_t :2; // Reserved bits
+ uint64_t maxtl:8; // Maximum trap level
+ 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;
+ };
+ 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;
+ };
+ uint64_t fcc0:2; // Floating-Point condtion codes
+ 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)
+ 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;
+ };
+ 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
+ uint64_t :26; // Reserved bits
+ } fsrFields;
+ };
+ union
+ {
+ uint8_t fprs; // Floating-Point Register State
+ struct
+ {
+ uint8_t dl:1; // Dirty lower
+ uint8_t du:1; // Dirty upper
+ uint8_t fef:1; // FPRS enable floating-Point
+ } fprsFields;
+ };
+
+ public:
+ MiscReg readReg(int misc_reg);
+
+ MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc);
+
+ Fault setReg(int misc_reg, const MiscReg &val);
+
+ Fault setRegWithEffect(int misc_reg, const MiscReg &val,
+ ExecContext *xc);
+
+ void serialize(std::ostream & os);
+
+ void unserialize(Checkpoint * cp, std::string & section);
+ };
+
+ typedef union
+ {
+ float32_t singReg;
+ float64_t doubReg;
+ float128_t quadReg;
+ } FloatReg;
+
+ 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
+ Addr nnpc;
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ StaticInstPtr decodeInst(MachInst);
+
+ // return a no-op instruction... used for instruction fetch faults
+ extern const MachInst NoopMachInst;
+
+ // Instruction address compression hooks
+ inline Addr realPCToFetchPC(const Addr &addr)
+ {
+ return addr;
+ }
+
+ inline Addr fetchPCToRealPC(const Addr &addr)
+ {
+ return addr;
+ }
+
+ // the size of "fetched" instructions (not necessarily the size
+ // of real instructions for PISA)
+ inline size_t fetchInstSize()
+ {
+ return sizeof(MachInst);
+ }
+
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param xc The execution context.
+ */
+ template <class XC>
+
+ static inline setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ // check for error condition. SPARC syscall convention is to
+ // indicate success/failure in reg the carry bit of the ccr
+ // and put the return value itself in the standard return value reg ().
+ if (return_value.successful()) {
+ // no error
+ regs->miscRegFile.ccrFields.iccFields.c = 0;
+ regs->intRegFile[ReturnValueReg] = return_value.value();
+ } else {
+ // got an error, return details
+ regs->miscRegFile.ccrFields.iccFields.c = 1;
+ regs->intRegFile[ReturnValueReg] = -return_value.value();
+ }
+ }
+};
+
+#if !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
+
+
+#if FULL_SYSTEM
+
+#include "arch/alpha/ev5.hh"
+#endif
+
+#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/arch/sparc/linux/process.cc b/arch/sparc/linux/process.cc
new file mode 100644
index 000000000..fa2a7b9f5
--- /dev/null
+++ b/arch/sparc/linux/process.cc
@@ -0,0 +1,374 @@
+/*
+ * 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/sparc/common_syscall_emul.hh"
+#include "arch/sparc/linux/process.hh"
+#include "arch/sparc/isa_traits.hh"
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/linux.hh"
+#include "mem/functional/functional.hh"
+
+#include "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace SparcISA;
+
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "Linux");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "2.4.20");
+ strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+ strcpy(name->machine, "sparc");
+
+ name.copyOut(xc->mem);
+ return 0;
+}
+
+SyscallDesc SparcLinuxProcess::syscallDescs[] = {
+ /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc);
+ /* 1 */ SyscallDesc("exit", exitFunc);
+ /* 2 */ SyscallDesc("fork", unimplementedFunc);
+ /* 3 */ SyscallDesc("read", readFunc);
+ /* 4 */ SyscallDesc("write", writeFunc);
+ /* 5 */ SyscallDesc("open", openFunc<Linux>);
+ /* 6 */ SyscallDesc("close", closeFinc);
+ /* 7 */ SyscallDesc("wait4", unimplementedFunc);
+ /* 8 */ SyscallDesc("creat", unimplementedFunc);
+ /* 9 */ SyscallDesc("link", unimplementedFunc);
+ /* 10 */ SyscallDesc("unlink", unlinkFunc);
+ /* 11 */ SyscallDesc("execv", unimplementedFunc);
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc);
+ /* 13 */ SyscallDesc("chown", chownFunc);
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc);
+ /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>);
+ /* 16 */ SyscallDesc("lchown", unimplementedFunc);
+ /* 17 */ SyscallDesc("brk", obreakFunc);
+ /* 18 */ SyscallDesc("perfctr", unimplementedFunc);
+ /* 19 */ SyscallDesc("lseek", lseekFunc);
+ /* 20 */ SyscallDesc("getpid", getpidFunc);
+ /* 21 */ SyscallDesc("capget", unimplementedFunc);
+ /* 22 */ SyscallDesc("capset", unimplementedFunc);
+ /* 23 */ SyscallDesc("setuid", setuidFunc);
+ /* 24 */ SyscallDesc("getuid", getuidFunc);
+ /* 25 */ SyscallDesc("time", unimplementedFunc);
+ /* 26 */ SyscallDesc("ptrace", unimplementedFunc);
+ /* 27 */ SyscallDesc("alarm", unimplementedFunc);
+ /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc);
+ /* 29 */ SyscallDesc("pause", unimplementedFunc);
+ /* 30 */ SyscallDesc("utime", unimplementedFunc);
+ /* 31 */ SyscallDesc("lchown32", unimplementedFunc);
+ /* 32 */ SyscallDesc("fchown32", unimplementedFunc);
+ /* 33 */ SyscallDesc("access", unimplementedFunc);
+ /* 34 */ SyscallDesc("nice", unimplementedFunc);
+ /* 35 */ SyscallDesc("chown32", unimplementedFunc);
+ /* 36 */ SyscallDesc("sync", unimplementedFunc);
+ /* 37 */ SyscallDesc("kill", unimplementedFunc);
+ /* 38 */ SyscallDesc("stat", unimplementedFunc);
+ /* 39 */ SyscallDesc("sendfile", unimplementedFunc);
+ /* 40 */ SyscallDesc("lstat", unimplementedFunc);
+ /* 41 */ SyscallDesc("dup", unimplementedFunc);
+ /* 42 */ SyscallDesc("pipe", pipePseudoFunc);
+ /* 43 */ SyscallDesc("times", unimplementedFunc);
+ /* 44 */ SyscallDesc("getuid32", unimplementedFunc);
+ /* 45 */ SyscallDesc("umount2", unimplementedFunc);
+ /* 46 */ SyscallDesc("setgid", unimplementedFunc);
+ /* 47 */ SyscallDesc("getgid", getgidFunc);
+ /* 48 */ SyscallDesc("signal", unimplementedFunc);
+ /* 49 */ SyscallDesc("geteuid", geteuidFunc);
+ /* 50 */ SyscallDesc("getegid", getegidFunc);
+ /* 51 */ SyscallDesc("acct", unimplementedFunc);
+ /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc);
+ /* 53 */ SyscallDesc("getgid32", unimplementedFunc);
+ /* 54 */ SyscallDesc("ioctl", unimplementedFunc);
+ /* 55 */ SyscallDesc("reboot", unimplementedFunc);
+ /* 56 */ SyscallDesc("mmap2", unimplementedFunc);
+ /* 57 */ SyscallDesc("symlink", unimplementedFunc);
+ /* 58 */ SyscallDesc("readlink", unimplementedFunc);
+ /* 59 */ SyscallDesc("execve", unimplementedFunc);
+ /* 60 */ SyscallDesc("umask", unimplementedFunc);
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc);
+ /* 62 */ SyscallDesc("fstat", unimplementedFunc);
+ /* 63 */ SyscallDesc("fstat64", unimplementedFunc);
+ /* 64 */ SyscallDesc("getpagesize", unimplementedFunc);
+ /* 65 */ SyscallDesc("msync", unimplementedFunc);
+ /* 66 */ SyscallDesc("vfork", unimplementedFunc);
+ /* 67 */ SyscallDesc("pread64", unimplementedFunc);
+ /* 68 */ SyscallDesc("pwrite64", unimplementedFunc);
+ /* 69 */ SyscallDesc("geteuid32", unimplementedFunc);
+ /* 70 */ SyscallDesc("getdgid32", unimplementedFunc);
+ /* 71 */ SyscallDesc("mmap", unimplementedFunc);
+ /* 72 */ SyscallDesc("setreuid32", unimplementedFunc);
+ /* 73 */ SyscallDesc("munmap", unimplementedFunc);
+ /* 74 */ SyscallDesc("mprotect", unimplementedFunc);
+ /* 75 */ SyscallDesc("madvise", unimplementedFunc);
+ /* 76 */ SyscallDesc("vhangup", unimplementedFunc);
+ /* 77 */ SyscallDesc("truncate64", unimplementedFunc);
+ /* 78 */ SyscallDesc("mincore", unimplementedFunc);
+ /* 79 */ SyscallDesc("getgroups", unimplementedFunc);
+ /* 80 */ SyscallDesc("setgroups", unimplementedFunc);
+ /* 81 */ SyscallDesc("getpgrp", unimplementedFunc);
+ /* 82 */ SyscallDesc("setgroups32", unimplementedFunc);
+ /* 83 */ SyscallDesc("setitimer", unimplementedFunc);
+ /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc);
+ /* 85 */ SyscallDesc("swapon", unimplementedFunc);
+ /* 86 */ SyscallDesc("getitimer", unimplementedFunc);
+ /* 87 */ SyscallDesc("setuid32", unimplementedFunc);
+ /* 88 */ SyscallDesc("sethostname", unimplementedFunc);
+ /* 89 */ SyscallDesc("setgid32", unimplementedFunc);
+ /* 90 */ SyscallDesc("dup2", unimplementedFunc);
+ /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc);
+ /* 92 */ SyscallDesc("fcntl", unimplementedFunc);
+ /* 93 */ SyscallDesc("select", unimplementedFunc);
+ /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc);
+ /* 95 */ SyscallDesc("fsync", unimplementedFunc);
+ /* 96 */ SyscallDesc("setpriority", unimplementedFunc);
+ /* 97 */ SyscallDesc("socket", unimplementedFunc);
+ /* 98 */ SyscallDesc("connect", unimplementedFunc);
+ /* 99 */ SyscallDesc("accept", unimplementedFunc);
+ /* 100 */ SyscallDesc("getpriority", unimplementedFunc);
+ /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc);
+ /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc);
+ /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc);
+ /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc);
+ /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc);
+ /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc);
+ /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc);
+ /* 108 */ SyscallDesc("setresuid", unimplementedFunc);
+ /* 109 */ SyscallDesc("getresuid", unimplementedFunc);
+ /* 110 */ SyscallDesc("setresgid", unimplementedFunc);
+ /* 111 */ SyscallDesc("getresgid", unimplementedFunc);
+ /* 112 */ SyscallDesc("setregid32", unimplementedFunc);
+ /* 113 */ SyscallDesc("recvmsg", unimplementedFunc);
+ /* 114 */ SyscallDesc("sendmsg", unimplementedFunc);
+ /* 115 */ SyscallDesc("getgroups32", unimplementedFunc);
+ /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc);
+ /* 117 */ SyscallDesc("getrusage", unimplementedFunc);
+ /* 118 */ SyscallDesc("getsockopt", unimplementedFunc);
+ /* 119 */ SyscallDesc("getcwd", unimplementedFunc);
+ /* 120 */ SyscallDesc("readv", unimplementedFunc);
+ /* 121 */ SyscallDesc("writev", unimplementedFunc);
+ /* 122 */ SyscallDesc("settimeofday", unimplementedFunc);
+ /* 123 */ SyscallDesc("fchown", unimplementedFunc);
+ /* 124 */ SyscallDesc("fchmod", unimplementedFunc);
+ /* 125 */ SyscallDesc("recvfrom", unimplementedFunc);
+ /* 126 */ SyscallDesc("setreuid", unimplementedFunc);
+ /* 127 */ SyscallDesc("setregid", unimplementedFunc);
+ /* 128 */ SyscallDesc("rename", unimplementedFunc);
+ /* 129 */ SyscallDesc("truncate", unimplementedFunc);
+ /* 130 */ SyscallDesc("ftruncate", unimplementedFunc);
+ /* 131 */ SyscallDesc("flock", unimplementedFunc);
+ /* 132 */ SyscallDesc("lstat64", unimplementedFunc);
+ /* 133 */ SyscallDesc("sendto", unimplementedFunc);
+ /* 134 */ SyscallDesc("shutdown", unimplementedFunc);
+ /* 135 */ SyscallDesc("socketpair", unimplementedFunc);
+ /* 136 */ SyscallDesc("mkdir", unimplementedFunc);
+ /* 137 */ SyscallDesc("rmdir", unimplementedFunc);
+ /* 138 */ SyscallDesc("utimes", unimplementedFunc);
+ /* 139 */ SyscallDesc("stat64", unimplementedFunc);
+ /* 140 */ SyscallDesc("sendfile64", unimplementedFunc);
+ /* 141 */ SyscallDesc("getpeername", unimplementedFunc);
+ /* 142 */ SyscallDesc("futex", unimplementedFunc);
+ /* 143 */ SyscallDesc("gettid", unimplementedFunc);
+ /* 144 */ SyscallDesc("getrlimit", unimplementedFunc);
+ /* 145 */ SyscallDesc("setrlimit", unimplementedFunc);
+ /* 146 */ SyscallDesc("pivot_root", unimplementedFunc);
+ /* 147 */ SyscallDesc("prctl", unimplementedFunc);
+ /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc);
+ /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc);
+ /* 150 */ SyscallDesc("getsockname", unimplementedFunc);
+ /* 151 */ SyscallDesc("inotify_init", unimplementedFunc);
+ /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc);
+ /* 153 */ SyscallDesc("poll", unimplementedFunc);
+ /* 154 */ SyscallDesc("getdents64", unimplementedFunc);
+ /* 155 */ SyscallDesc("fcntl64", unimplementedFunc);
+ /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc);
+ /* 157 */ SyscallDesc("statfs", unimplementedFunc);
+ /* 158 */ SyscallDesc("fstatfs", unimplementedFunc);
+ /* 159 */ SyscallDesc("umount", unimplementedFunc);
+ /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc);
+ /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc);
+ /* 162 */ SyscallDesc("getdomainname", unimplementedFunc);
+ /* 163 */ SyscallDesc("setdomainname", unimplementedFunc);
+ /* 164 */ SyscallDesc("utrap_install", unimplementedFunc);
+ /* 165 */ SyscallDesc("quotactl", unimplementedFunc);
+ /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc);
+ /* 167 */ SyscallDesc("mount", unimplementedFunc);
+ /* 168 */ SyscallDesc("ustat", unimplementedFunc);
+ /* 169 */ SyscallDesc("setxattr", unimplementedFunc);
+ /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc);
+ /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc);
+ /* 172 */ SyscallDesc("getxattr", unimplementedFunc);
+ /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc);
+ /* 174 */ SyscallDesc("getdents", unimplementedFunc);
+ /* 175 */ SyscallDesc("setsid", unimplementedFunc);
+ /* 176 */ SyscallDesc("fchdir", unimplementedFunc);
+ /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc);
+ /* 178 */ SyscallDesc("listxattr", unimplementedFunc);
+ /* 179 */ SyscallDesc("llistxattr", unimplementedFunc);
+ /* 180 */ SyscallDesc("flistxattr", unimplementedFunc);
+ /* 181 */ SyscallDesc("removexattr", unimplementedFunc);
+ /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc);
+ /* 183 */ SyscallDesc("sigpending", unimplementedFunc);
+ /* 184 */ SyscallDesc("query_module", unimplementedFunc);
+ /* 185 */ SyscallDesc("setpgid", unimplementedFunc);
+ /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc);
+ /* 187 */ SyscallDesc("tkill", unimplementedFunc);
+ /* 188 */ SyscallDesc("exit_group", unimplementedFunc);
+ /* 189 */ SyscallDesc("uname", unameFunc);
+ /* 190 */ SyscallDesc("init_module", unimplementedFunc);
+ /* 191 */ SyscallDesc("personality", unimplementedFunc);
+ /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc);
+ /* 193 */ SyscallDesc("epoll_create", unimplementedFunc);
+ /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc);
+ /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc);
+ /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc);
+ /* 197 */ SyscallDesc("getppid", getppidFunc);
+ /* 198 */ SyscallDesc("sigaction", unimplementedFunc);
+ /* 199 */ SyscallDesc("sgetmask", unimplementedFunc);
+ /* 200 */ SyscallDesc("ssetmask", unimplementedFunc);
+ /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc);
+ /* 202 */ SyscallDesc("oldlstat", unimplementedFunc);
+ /* 203 */ SyscallDesc("uselib", unimplementedFunc);
+ /* 204 */ SyscallDesc("readdir", unimplementedFunc);
+ /* 205 */ SyscallDesc("readahead", unimplementedFunc);
+ /* 206 */ SyscallDesc("socketcall", unimplementedFunc);
+ /* 207 */ SyscallDesc("syslog", unimplementedFunc);
+ /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc);
+ /* 209 */ SyscallDesc("fadvise64", unimplementedFunc);
+ /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc);
+ /* 211 */ SyscallDesc("tgkill", unimplementedFunc);
+ /* 212 */ SyscallDesc("waitpid", unimplementedFunc);
+ /* 213 */ SyscallDesc("swapoff", unimplementedFunc);
+ /* 214 */ SyscallDesc("sysinfo", unimplementedFunc);
+ /* 215 */ SyscallDesc("ipc", unimplementedFunc);
+ /* 216 */ SyscallDesc("sigreturn", unimplementedFunc);
+ /* 217 */ SyscallDesc("clone", unimplementedFunc);
+ /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc);
+ /* 219 */ SyscallDesc("adjtimex", unimplementedFunc);
+ /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc);
+ /* 221 */ SyscallDesc("create_module", unimplementedFunc);
+ /* 222 */ SyscallDesc("delete_module", unimplementedFunc);
+ /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc);
+ /* 224 */ SyscallDesc("getpgid", unimplementedFunc);
+ /* 225 */ SyscallDesc("bdflush", unimplementedFunc);
+ /* 226 */ SyscallDesc("sysfs", unimplementedFunc);
+ /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc);
+ /* 228 */ SyscallDesc("setfsuid", unimplementedFunc);
+ /* 229 */ SyscallDesc("setfsgid", unimplementedFunc);
+ /* 230 */ SyscallDesc("_newselect", unimplementedFunc);
+ /* 231 */ SyscallDesc("time", unimplementedFunc);
+ /* 232 */ SyscallDesc("oldstat", unimplementedFunc);
+ /* 233 */ SyscallDesc("stime", unimplementedFunc);
+ /* 234 */ SyscallDesc("statfs64", unimplementedFunc);
+ /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc);
+ /* 236 */ SyscallDesc("_llseek", unimplementedFunc);
+ /* 237 */ SyscallDesc("mlock", unimplementedFunc);
+ /* 238 */ SyscallDesc("munlock", unimplementedFunc);
+ /* 239 */ SyscallDesc("mlockall", unimplementedFunc);
+ /* 240 */ SyscallDesc("munlockall", unimplementedFunc);
+ /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc);
+ /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc);
+ /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc);
+ /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc);
+ /* 245 */ SyscallDesc("sched_yield", unimplementedFunc);
+ /* 246 */ SyscallDesc("sched_get_priority_max", unimplimented);
+ /* 247 */ SyscallDesc("sched_get_priority_min", unimplimented);
+ /* 248 */ SyscallDesc("sched_rr_get_interval", unimplimented);
+ /* 249 */ SyscallDesc("nanosleep", unimplementedFunc);
+ /* 250 */ SyscallDesc("mremap", unimplementedFunc);
+ /* 251 */ SyscallDesc("_sysctl", unimplementedFunc);
+ /* 252 */ SyscallDesc("getsid", unimplementedFunc);
+ /* 253 */ SyscallDesc("fdatasync", unimplementedFunc);
+ /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc);
+ /* 255 */ SyscallDesc("aplib", unimplementedFunc);
+ /* 256 */ SyscallDesc("clock_settime", unimplementedFunc);
+ /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc);
+ /* 258 */ SyscallDesc("clock_getres", unimplementedFunc);
+ /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc);
+ /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc);
+ /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc);
+ /* 262 */ SyscallDesc("timer_settime", unimplementedFunc);
+ /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc);
+ /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc);
+ /* 265 */ SyscallDesc("timer_delete", unimplementedFunc);
+ /* 266 */ SyscallDesc("timer_create", unimplementedFunc);
+ /* 267 */ SyscallDesc("vserver", unimplementedFunc);
+ /* 268 */ SyscallDesc("io_setup", unimplementedFunc);
+ /* 269 */ SyscallDesc("io_destroy", unimplementedFunc);
+ /* 270 */ SyscallDesc("io_submit", unimplementedFunc);
+ /* 271 */ SyscallDesc("io_cancel", unimplementedFunc);
+ /* 272 */ SyscallDesc("io_getevents", unimplementedFunc);
+ /* 273 */ SyscallDesc("mq_open", unimplementedFunc);
+ /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc);
+ /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc);
+ /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc);
+ /* 277 */ SyscallDesc("mq_notify", unimplementedFunc);
+ /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc);
+ /* 279 */ SyscallDesc("waitid", unimplementedFunc);
+ /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc);
+ /* 281 */ SyscallDesc("add_key", unimplementedFunc);
+ /* 282 */ SyscallDesc("request_key", unimplementedFunc);
+ /* 283 */ SyscallDesc("keyctl", unimplementedFunc);
+};
+
+SparcLinuxProcess::SparcLinuxProcess(const std::string &name,
+ ObjectFile *objFile,
+ int stdin_fd,
+ int stdout_fd,
+ int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp)
+ : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
+{
+ // The sparc syscall table must be <= 283 entries because that is all there
+ // is space for.
+ assert(Num_Syscall_Descs <= 283);
+
+ init_regs->intRegFile[0] = 0;
+}
+
+
+
+SyscallDesc*
+AlphaLinuxProcess::getDesc(int callnum)
+{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
+}
diff --git a/arch/sparc/linux/process.hh b/arch/sparc/linux/process.hh
new file mode 100644
index 000000000..c41406b4b
--- /dev/null
+++ b/arch/sparc/linux/process.hh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef __SPARC_LINUX_PROCESS_HH__
+#define __SPARC_LINUX_PROCESS_HH__
+
+#include "sim/process.hh"
+
+
+/// A process with emulated SPARC/Linux syscalls.
+class SparcLinuxProcess : public LiveProcess
+{
+ public:
+ /// Constructor.
+ SparcLinuxProcess(const std::string &name,
+ ObjectFile *objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
+
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
+};
+
+
+#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/arch/sparc/process.cc b/arch/sparc/process.cc
new file mode 100644
index 000000000..53a215379
--- /dev/null
+++ b/arch/sparc/process.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#include "arch/sparc/process.hh"
+
+namespace SparcISA
+{
+
+LiveProcess *
+createProcess(const string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ vector<string> &argv, vector<string> &envp)
+{
+ LiveProcess * process = NULL;
+ if (objFile->getArch() != ObjectFile::SPARC)
+ fatal("Object file does not match architecture.");
+ switch (objFile->getOpSys()) {
+ case ObjectFile::Linux:
+ process = new SparcLinuxProcess(nm, objFile,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ case ObjectFile::Solaris:
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+ return process;
+}
+
+} // namespace SparcISA
diff --git a/arch/sparc/process.hh b/arch/sparc/process.hh
new file mode 100644
index 000000000..48041a316
--- /dev/null
+++ b/arch/sparc/process.hh
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#ifndef __SPARC_PROCESS_HH__
+#define __SPARC_PROCESS_HH__
+
+#include "arch/sparc/linux/process.hh"
+#include "base/loader/object_file.hh"
+
+namespace SparcISA
+{
+
+LiveProcess *
+createProcess(const string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ vector<string> &argv, vector<string> &envp);
+
+} // namespace SparcISA
+
+#endif // __SPARC_PROCESS_HH__
diff --git a/arch/sparc/stacktrace.hh b/arch/sparc/stacktrace.hh
new file mode 100644
index 000000000..1d8d97a79
--- /dev/null
+++ b/arch/sparc/stacktrace.hh
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_STACKTRACE_HH__
+#define __ARCH_ALPHA_STACKTRACE_HH__
+
+#include "base/trace.hh"
+#include "cpu/static_inst.hh"
+
+class ExecContext;
+class StackTrace;
+
+class ProcessInfo
+{
+ private:
+ ExecContext *xc;
+
+ int thread_info_size;
+ int task_struct_size;
+ int task_off;
+ int pid_off;
+ int name_off;
+
+ public:
+ ProcessInfo(ExecContext *_xc);
+
+ Addr task(Addr ksp) const;
+ int pid(Addr ksp) const;
+ std::string name(Addr ksp) const;
+};
+
+class StackTrace
+{
+ protected:
+ typedef TheISA::MachInst MachInst;
+ private:
+ ExecContext *xc;
+ std::vector<Addr> stack;
+
+ private:
+ bool isEntry(Addr addr);
+ bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
+ bool decodeSave(MachInst inst, int &reg, int &disp);
+ bool decodeStack(MachInst inst, int &disp);
+
+ void trace(ExecContext *xc, bool is_call);
+
+ public:
+ StackTrace();
+ StackTrace(ExecContext *xc, StaticInstPtr inst);
+ ~StackTrace();
+
+ void clear()
+ {
+ xc = 0;
+ stack.clear();
+ }
+
+ bool valid() const { return xc != NULL; }
+ bool trace(ExecContext *xc, StaticInstPtr inst);
+
+ public:
+ const std::vector<Addr> &getstack() const { return stack; }
+
+ static const int user = 1;
+ static const int console = 2;
+ static const int unknown = 3;
+
+#if TRACING_ON
+ private:
+ void dump();
+
+ public:
+ void dprintf() { if (DTRACE(Stack)) dump(); }
+#else
+ public:
+ void dprintf() {}
+#endif
+};
+
+inline bool
+StackTrace::trace(ExecContext *xc, StaticInstPtr inst)
+{
+ if (!inst->isCall() && !inst->isReturn())
+ return false;
+
+ if (valid())
+ clear();
+
+ trace(xc, !inst->isReturn());
+ return true;
+}
+
+#endif // __ARCH_ALPHA_STACKTRACE_HH__
diff --git a/base/intmath.hh b/base/intmath.hh
index 198278d6f..51baddb91 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/elf_object.cc b/base/loader/elf_object.cc
index 52f236fef..1136686f0 100644
--- a/base/loader/elf_object.cc
+++ b/base/loader/elf_object.cc
@@ -38,8 +38,8 @@
#define __LIBELF_NEED_LINK_H 0
#define __LIBELF_SYMBOL_VERSIONS 0
-#include <libelf/libelf.h>
-#include <libelf/gelf.h>
+#include "libelf/libelf.h"
+#include "libelf/gelf.h"
#include "base/loader/elf_object.hh"
@@ -55,6 +55,8 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
{
Elf *elf;
GElf_Ehdr ehdr;
+ Arch arch = UnknownArch;
+ OpSys opSys = UnknownOpSys;
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
@@ -72,17 +74,87 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
return NULL;
}
else {
- if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
- panic("32 bit ELF Binary, Not Supported");
- /* @todo this emachine value isn't offical yet.
- * so we probably shouldn't check it. */
-// if (ehdr.e_machine != EM_ALPHA)
-// panic("Non Alpha Binary, Not Supported");
+ //Detect the architecture
+ //Versioning issues in libelf need to be resolved to get the correct
+ //SPARC constants.
+ //If MIPS supports 32 bit executables, this may need to be changed.
+ //Also, there are other MIPS constants which may be used, like
+ //EM_MIPS_RS3_LE and EM_MIPS_X
+ //Since we don't know how to check for alpha right now, we'll
+ //just assume if it wasn't something else and it's 64 bit, that's
+ //what it must be.
+ if (ehdr.e_machine == EM_SPARC64 ||
+ ehdr.e_machine == EM_SPARC ||
+ ehdr.e_machine == EM_SPARCV9) {
+ arch = ObjectFile::SPARC;
+ } else if (ehdr.e_machine == EM_MIPS
+ && ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+ arch = ObjectFile::MIPS;
+ } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+ arch = ObjectFile::Alpha;
+ } else {
+ arch = ObjectFile::UnknownArch;
+ }
- elf_end(elf);
+ //Detect the operating system
+ switch (ehdr.e_ident[EI_OSABI])
+ {
+
+ case ELFOSABI_LINUX:
+ opSys = ObjectFile::Linux;
+ break;
+ case ELFOSABI_SOLARIS:
+ opSys = ObjectFile::Solaris;
+ break;
+ case ELFOSABI_TRU64:
+ opSys = ObjectFile::Tru64;
+ break;
+ default:
+ opSys = ObjectFile::UnknownOpSys;
+ }
- return new ElfObject(fname, fd, len, data,
- ObjectFile::Alpha, ObjectFile::Linux);
+ //take a look at the .note.ABI section
+ //It can let us know what's what.
+ if (opSys == ObjectFile::UnknownOpSys)
+ {
+ Elf_Scn *section;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ uint32_t osAbi;;
+ int secIdx = 1;
+
+ // Get the first section
+ section = elf_getscn(elf, secIdx);
+
+ // While there are no more sections
+ while (section != NULL) {
+ gelf_getshdr(section, &shdr);
+ if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
+ elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
+ // we have found a ABI note section
+ // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
+ // 2 == solaris, 3 == freebsd
+ data = elf_rawdata(section, NULL);
+ assert(data->d_buf);
+ if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ osAbi = htole(((uint32_t*)data->d_buf)[4]);
+ else
+ osAbi = htobe(((uint32_t*)data->d_buf)[4]);
+
+ switch(osAbi) {
+ case 0:
+ opSys = ObjectFile::Linux;
+ break;
+ case 2:
+ opSys = ObjectFile::Solaris;
+ break;
+ }
+ } // if section found
+ section = elf_getscn(elf, ++secIdx);
+ } // while sections
+ }
+ elf_end(elf);
+ return new ElfObject(fname, fd, len, data, arch, opSys);
}
}
diff --git a/base/loader/exec_aout.h b/base/loader/exec_aout.h
index 76ebe9bb5..eed44baee 100644
--- a/base/loader/exec_aout.h
+++ b/base/loader/exec_aout.h
@@ -55,6 +55,7 @@
(N_GETMAGIC(ex) != NMAGIC && N_GETMAGIC(ex) != OMAGIC && \
N_GETMAGIC(ex) != ZMAGIC)
-#include "targetarch/aout_machdep.h"
+//Only alpha will be able to load aout for now
+#include "arch/alpha/aout_machdep.h"
#endif /* !_SYS_EXEC_AOUT_H_ */
diff --git a/base/loader/exec_ecoff.h b/base/loader/exec_ecoff.h
index 4eece4318..555589806 100644
--- a/base/loader/exec_ecoff.h
+++ b/base/loader/exec_ecoff.h
@@ -37,7 +37,8 @@
#ifndef _SYS_EXEC_ECOFF_H_
#define _SYS_EXEC_ECOFF_H_
-#include "targetarch/ecoff_machdep.h"
+//Only alpha will be able to load ecoff files for now
+#include "arch/alpha/ecoff_machdep.h"
struct ecoff_filehdr {
coff_ushort f_magic; /* magic number */
diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh
index 35ea11b54..08a51863e 100644
--- a/base/loader/object_file.hh
+++ b/base/loader/object_file.hh
@@ -29,7 +29,9 @@
#ifndef __OBJECT_FILE_HH__
#define __OBJECT_FILE_HH__
-#include "targetarch/isa_traits.hh" // for Addr
+#include <string>
+
+#include "sim/host.hh" // for Addr
class TranslatingPort;
class SymbolTable;
@@ -40,13 +42,16 @@ class ObjectFile
enum Arch {
UnknownArch,
- Alpha
+ Alpha,
+ SPARC,
+ MIPS
};
enum OpSys {
UnknownOpSys,
Tru64,
- Linux
+ Linux,
+ Solaris
};
protected:
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/refcnt.hh b/base/refcnt.hh
index 9d9ed4337..de589f7c5 100644
--- a/base/refcnt.hh
+++ b/base/refcnt.hh
@@ -29,6 +29,8 @@
#ifndef __REFCNT_HH__
#define __REFCNT_HH__
+#include <stddef.h> //For the NULL macro definition
+
class RefCounted
{
private:
diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc
index 67d745d43..84093459c 100644
--- a/base/remote_gdb.cc
+++ b/base/remote_gdb.cc
@@ -129,9 +129,10 @@
#include "cpu/static_inst.hh"
#include "mem/functional/physical.hh"
#include "sim/system.hh"
-#include "targetarch/vtophys.hh"
+#include "arch/vtophys.hh"
using namespace std;
+using namespace TheISA;
#ifndef NDEBUG
vector<RemoteGDB *> debuggers;
@@ -370,7 +371,7 @@ RemoteGDB::acc(Addr va, size_t len)
if (AlphaISA::PcPAL(va) || va < 0x10000)
return true;
- Addr ptbr = context->regs.ipr[AlphaISA::IPR_PALtemp20];
+ Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va);
if (!pte.valid()) {
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
@@ -423,12 +424,25 @@ void
RemoteGDB::getregs()
{
memset(gdbregs, 0, sizeof(gdbregs));
- memcpy(&gdbregs[KGDB_REG_V0], context->regs.intRegFile, 32 * sizeof(uint64_t));
+
+ gdbregs[KGDB_REG_PC] = context->readPC();
+
+ // @todo: Currently this is very Alpha specific.
+ if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
+ }
+ } else {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ gdbregs[i] = context->readIntReg(i);
+ }
+ }
+
#ifdef KGDB_FP_REGS
- memcpy(&gdbregs[KGDB_REG_F0], context->regs.floatRegFile.q,
- 32 * sizeof(uint64_t));
+ for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
+ gdbregs[i + KGDB_REG_F0] = context->readFloatRegInt(i);
+ }
#endif
- gdbregs[KGDB_REG_PC] = context->regs.pc;
}
///////////////////////////////////////////////////////////
@@ -440,13 +454,23 @@ RemoteGDB::getregs()
void
RemoteGDB::setregs()
{
- memcpy(context->regs.intRegFile, &gdbregs[KGDB_REG_V0],
- 32 * sizeof(uint64_t));
+ // @todo: Currently this is very Alpha specific.
+ if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]);
+ }
+ } else {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ context->setIntReg(i, gdbregs[i]);
+ }
+ }
+
#ifdef KGDB_FP_REGS
- memcpy(context->regs.floatRegFile.q, &gdbregs[KGDB_REG_F0],
- 32 * sizeof(uint64_t));
+ for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
+ context->setFloatRegInt(i, gdbregs[i + KGDB_REG_F0]);
+ }
#endif
- context->regs.pc = gdbregs[KGDB_REG_PC];
+ context->setPC(gdbregs[KGDB_REG_PC]);
}
void
@@ -485,7 +509,7 @@ RemoteGDB::clearSingleStep()
void
RemoteGDB::setSingleStep()
{
- Addr pc = context->regs.pc;
+ Addr pc = context->readPC();
Addr npc, bpc;
bool set_bt = false;
@@ -494,7 +518,7 @@ RemoteGDB::setSingleStep()
// User was stopped at pc, e.g. the instruction at pc was not
// executed.
MachInst inst = read<MachInst>(pc);
- StaticInstPtr<TheISA> si(inst);
+ StaticInstPtr si(inst);
if (si->hasBranchTarget(pc, context, bpc)) {
// Don't bother setting a breakpoint on the taken branch if it
// is the same as the next pc
@@ -834,7 +858,7 @@ RemoteGDB::trap(int type)
return false;
DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
- context->regs.pc, context->regs.npc);
+ context->readPC(), context->readNextPC());
clearSingleStep();
@@ -989,8 +1013,8 @@ RemoteGDB::trap(int type)
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
clearSingleStep();
goto out;
@@ -998,8 +1022,8 @@ RemoteGDB::trap(int type)
case KGDB_CONT:
if (p - data < datalen) {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
clearSingleStep();
goto out;
@@ -1008,8 +1032,8 @@ RemoteGDB::trap(int type)
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
setSingleStep();
goto out;
@@ -1017,8 +1041,8 @@ RemoteGDB::trap(int type)
case KGDB_STEP:
if (p - data < datalen) {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
setSingleStep();
goto out;
diff --git a/base/remote_gdb.hh b/base/remote_gdb.hh
index 652a58317..b7abf5116 100644
--- a/base/remote_gdb.hh
+++ b/base/remote_gdb.hh
@@ -43,6 +43,8 @@ class PhysicalMemory;
class GDBListener;
class RemoteGDB
{
+ protected:
+ typedef TheISA::MachInst MachInst;
private:
friend void debugger();
friend class GDBListener;
diff --git a/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..306d3a9dc 100644
--- a/build/SConstruct
+++ b/build/SConstruct
@@ -218,12 +218,18 @@ if have_mysql:
env = conf.Finish()
+# Define the universe of supported ISAs
+env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
+
+# Define the universe of supported CPU models
+env['ALL_CPU_LIST'] = ['SimpleCPU', 'FastCPU', 'FullCPU', 'AlphaFullCPU']
+
# Sticky options get saved in the options file so they persist from
# one invocation to the next (unless overridden, in which case the new
# value becomes sticky).
sticky_opts = Options(args=ARGUMENTS)
sticky_opts.AddOptions(
- EnumOption('TARGET_ISA', 'Target ISA', 'alpha', ('alpha')),
+ EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']),
BoolOption('FULL_SYSTEM', 'Full-system support', False),
BoolOption('ALPHA_TLASER',
'Model Alpha TurboLaser platform (vs. Tsunami)', False),
@@ -248,6 +254,12 @@ sticky_opts.AddOptions(
# Non-sticky options only apply to the current build.
nonsticky_opts = Options(args=ARGUMENTS)
nonsticky_opts.AddOptions(
+ # This really should be a sticky option, but there's a bug in
+ # scons 0.96.1 that causes ListOptions not to be able to be
+ # restored from a saved option file. It looks like this is fixed
+ # in 0.96.9, but there's a different bug in that version that means we
+ # can't just upgrade.
+ ListOption('CPU_MODELS', 'CPU models', 'all', env['ALL_CPU_LIST']),
BoolOption('update_ref', 'Update test reference outputs', False)
)
@@ -320,16 +332,20 @@ 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 = []
# Name of default options file is taken from 'default=' on command
# line if set, otherwise name of build dir.
- default_options_file = os.path.join('build_options', 'default',
+ default_options_file = os.path.join('default_options',
ARGUMENTS.get('default', build_dir))
if os.path.isfile(default_options_file):
sticky_opts.files.append(default_options_file)
- current_options_file = os.path.join('build_options', 'current', build_dir)
+ current_options_file = os.path.join('options', build_dir)
if os.path.isfile(current_options_file):
sticky_opts.files.append(current_options_file)
else:
@@ -339,7 +355,7 @@ for build_dir in build_dirs:
if not os.path.isdir(opt_dir):
os.mkdir(opt_dir)
if not sticky_opts.files:
- print "%s: No options file found in build_options, using defaults." \
+ print "%s: No options file found in options, using defaults." \
% build_dir
# Apply current option settings to env
diff --git a/build/build_options/default/ALPHA_FS b/build/default_options/ALPHA_FS
index ddd69b9b3..ddd69b9b3 100644
--- a/build/build_options/default/ALPHA_FS
+++ b/build/default_options/ALPHA_FS
diff --git a/build/build_options/default/ALPHA_FS_TL b/build/default_options/ALPHA_FS_TL
index 4f3e201ec..4f3e201ec 100644
--- a/build/build_options/default/ALPHA_FS_TL
+++ b/build/default_options/ALPHA_FS_TL
diff --git a/build/build_options/default/ALPHA_SE b/build/default_options/ALPHA_SE
index 3fedc22ca..3fedc22ca 100644
--- a/build/build_options/default/ALPHA_SE
+++ b/build/default_options/ALPHA_SE
diff --git a/build/default_options/MIPS_SE b/build/default_options/MIPS_SE
new file mode 100644
index 000000000..e74e2f69c
--- /dev/null
+++ b/build/default_options/MIPS_SE
@@ -0,0 +1,2 @@
+TARGET_ISA = 'mips'
+FULL_SYSTEM = 0
diff --git a/build/default_options/SPARC_SE b/build/default_options/SPARC_SE
new file mode 100644
index 000000000..3b256fc34
--- /dev/null
+++ b/build/default_options/SPARC_SE
@@ -0,0 +1,2 @@
+TARGET_ISA = 'sparc'
+FULL_SYSTEM = 0
diff --git a/cpu/SConscript b/cpu/SConscript
new file mode 100644
index 000000000..af6bab4eb
--- /dev/null
+++ b/cpu/SConscript
@@ -0,0 +1,129 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import os.path
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+#################################################################
+#
+# Generate StaticInst execute() method signatures.
+#
+# There must be one signature for each CPU model compiled in.
+# Since the set of compiled-in models is flexible, we generate a
+# header containing the appropriate set of signatures on the fly.
+#
+#################################################################
+
+# CPU model-specific data is contained in cpu_models.py
+# Convert to SCons File node to get path handling
+models_db = File('cpu_models.py')
+# slurp in contents of file
+execfile(models_db.srcnode().abspath)
+
+# Template for execute() signature.
+exec_sig_template = '''
+virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0;
+'''
+
+# Generate header.
+def gen_cpu_exec_signatures(target, source, env):
+ f = open(str(target[0]), 'w')
+ print >> f, '''
+#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
+#define __CPU_STATIC_INST_EXEC_SIGS_HH__
+'''
+ for cpu in env['CPU_MODELS']:
+ xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
+ print >> f, exec_sig_template % xc_type
+ print >> f, '''
+#endif // __CPU_STATIC_INST_EXEC_SIGS_HH__
+'''
+
+# Generate string that gets printed when header is rebuilt
+def gen_sigs_string(target, source, env):
+ return "Generating static_inst_exec_sigs.hh: " \
+ + ', '.join(env['CPU_MODELS'])
+
+# Add command to generate header to environment.
+env.Command('static_inst_exec_sigs.hh', models_db,
+ Action(gen_cpu_exec_signatures, gen_sigs_string,
+ varlist = ['CPU_MODELS']))
+
+#################################################################
+#
+# Include CPU-model-specific files based on set of models
+# specified in CPU_MODELS build option.
+#
+#################################################################
+
+sources = []
+
+if 'SimpleCPU' in env['CPU_MODELS']:
+ sources += Split('simple/cpu.cc')
+
+if 'FastCPU' in env['CPU_MODELS']:
+ sources += Split('fast/cpu.cc')
+
+if 'AlphaFullCPU' in env['CPU_MODELS']:
+ sources += Split('''
+ o3/2bit_local_pred.cc
+ o3/alpha_dyn_inst.cc
+ o3/alpha_cpu.cc
+ o3/alpha_cpu_builder.cc
+ o3/bpred_unit.cc
+ o3/btb.cc
+ o3/commit.cc
+ o3/decode.cc
+ o3/fetch.cc
+ o3/free_list.cc
+ o3/cpu.cc
+ o3/iew.cc
+ o3/inst_queue.cc
+ o3/ldstq.cc
+ o3/mem_dep_unit.cc
+ o3/ras.cc
+ o3/rename.cc
+ o3/rename_map.cc
+ o3/rob.cc
+ o3/sat_counter.cc
+ o3/store_set.cc
+ o3/tournament_pred.cc
+ ''')
+
+# FullCPU sources are included from m5/SConscript since they're not
+# below this point in the file hierarchy.
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+Return('sources')
+
diff --git a/cpu/base.cc b/cpu/base.cc
index 154143712..9ce458c64 100644
--- a/cpu/base.cc
+++ b/cpu/base.cc
@@ -39,10 +39,16 @@
#include "cpu/profile.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/param.hh"
+#include "sim/process.hh"
#include "sim/sim_events.hh"
+#include "sim/system.hh"
#include "base/trace.hh"
+#if FULL_SYSTEM
+#include "kern/kernel_stats.hh"
+#endif
+
using namespace std;
vector<BaseCPU *> BaseCPU::cpuList;
@@ -147,7 +153,10 @@ BaseCPU::BaseCPU(Params *p)
profileEvent = NULL;
if (params->profile)
profileEvent = new ProfileEvent(this, params->profile);
+
+ kernelStats = new Kernel::Statistics(system);
#endif
+
}
BaseCPU::Params::Params()
@@ -165,6 +174,10 @@ BaseCPU::enableFunctionTrace()
BaseCPU::~BaseCPU()
{
+#if FULL_SYSTEM
+ if (kernelStats)
+ delete kernelStats;
+#endif
}
void
@@ -203,6 +216,11 @@ BaseCPU::regStats()
}
} else if (size == 1)
execContexts[0]->regStats(name());
+
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->regStats(name() + ".kern");
+#endif
}
@@ -217,9 +235,9 @@ BaseCPU::registerExecContexts()
if (id != -1)
id += i;
- xc->cpu_id = system->registerExecContext(xc, id);
+ xc->setCpuId(system->registerExecContext(xc, id));
#else
- xc->cpu_id = xc->process->registerExecContext(xc);
+ xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
#endif
}
}
@@ -241,23 +259,22 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
ExecContext *oldXC = oldCPU->execContexts[i];
newXC->takeOverFrom(oldXC);
- assert(newXC->cpu_id == oldXC->cpu_id);
+ assert(newXC->readCpuId() == oldXC->readCpuId());
#if FULL_SYSTEM
- system->replaceExecContext(newXC, newXC->cpu_id);
+ system->replaceExecContext(newXC, newXC->readCpuId());
#else
- assert(newXC->process == oldXC->process);
- newXC->process->replaceExecContext(newXC, newXC->cpu_id);
+ assert(newXC->getProcessPtr() == oldXC->getProcessPtr());
+ newXC->getProcessPtr()->replaceExecContext(newXC, newXC->readCpuId());
#endif
}
#if FULL_SYSTEM
- for (int i = 0; i < NumInterruptLevels; ++i)
+ for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
interrupts[i] = oldCPU->interrupts[i];
intstatus = oldCPU->intstatus;
for (int i = 0; i < execContexts.size(); ++i)
- if (execContexts[i]->profile)
- execContexts[i]->profile->clear();
+ execContexts[i]->profileClear();
if (profileEvent)
profileEvent->schedule(curTick);
@@ -275,7 +292,7 @@ BaseCPU::ProfileEvent::process()
{
for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
ExecContext *xc = cpu->execContexts[i];
- xc->profile->sample(xc->profileNode, xc->profilePC);
+ xc->profileSample();
}
schedule(curTick + interval);
@@ -286,7 +303,7 @@ BaseCPU::post_interrupt(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
- if (int_num < 0 || int_num >= NumInterruptLevels)
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8)
@@ -302,7 +319,7 @@ BaseCPU::clear_interrupt(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
- if (int_num < 0 || int_num >= NumInterruptLevels)
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8)
@@ -326,15 +343,26 @@ BaseCPU::clear_interrupts()
void
BaseCPU::serialize(std::ostream &os)
{
- SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+ SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
SERIALIZE_SCALAR(intstatus);
+
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->serialize(os);
+#endif
+
}
void
BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+ UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
UNSERIALIZE_SCALAR(intstatus);
+
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->unserialize(cp, section);
+#endif
}
#endif // FULL_SYSTEM
diff --git a/cpu/base.hh b/cpu/base.hh
index c0e087f42..0866b49a7 100644
--- a/cpu/base.hh
+++ b/cpu/base.hh
@@ -36,9 +36,10 @@
#include "cpu/sampler/sampler.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
class System;
+namespace Kernel { class Statistics; }
class BranchPred;
class ExecContext;
class Port;
@@ -56,7 +57,7 @@ class BaseCPU : public SimObject
#if FULL_SYSTEM
protected:
- uint64_t interrupts[NumInterruptLevels];
+ uint64_t interrupts[TheISA::NumInterruptLevels];
uint64_t intstatus;
public:
@@ -66,7 +67,7 @@ class BaseCPU : public SimObject
bool checkInterrupts;
bool check_interrupt(int int_num) const {
- if (int_num > NumInterruptLevels)
+ if (int_num > TheISA::NumInterruptLevels)
panic("int_num out of bounds\n");
return interrupts[int_num] != 0;
@@ -138,6 +139,8 @@ class BaseCPU : public SimObject
virtual void startup();
virtual void regStats();
+ virtual void activateWhenReady(int tid) {};
+
void registerExecContexts();
/// Prepare for another CPU to take over execution. When it is
@@ -230,6 +233,10 @@ class BaseCPU : public SimObject
public:
// Number of CPU cycles simulated
Stats::Scalar<> numCycles;
+
+#if FULL_SYSTEM
+ Kernel::Statistics *kernelStats;
+#endif
};
#endif // __CPU_BASE_HH__
diff --git a/cpu/base_dyn_inst.cc b/cpu/base_dyn_inst.cc
index d921bd148..bf7c35cad 100644
--- a/cpu/base_dyn_inst.cc
+++ b/cpu/base_dyn_inst.cc
@@ -36,7 +36,7 @@
#include "base/cprintf.hh"
#include "base/trace.hh"
-#include "arch/alpha/faults.hh"
+#include "arch/faults.hh"
#include "cpu/exetrace.hh"
#include "mem/mem_req.hh"
@@ -45,6 +45,7 @@
#include "cpu/o3/alpha_cpu.hh"
using namespace std;
+using namespace TheISA;
#define NOHASH
#ifndef NOHASH
@@ -67,7 +68,7 @@ template <class Impl>
BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC,
Addr pred_PC, InstSeqNum seq_num,
FullCPU *cpu)
- : staticInst(machInst), traceData(NULL), cpu(cpu), xc(cpu->xcBase())
+ : staticInst(machInst), traceData(NULL), cpu(cpu), cpuXC(cpu->cpuXCBase())
{
seqNum = seq_num;
@@ -79,7 +80,7 @@ BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC,
}
template <class Impl>
-BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst)
+BaseDynInst<Impl>::BaseDynInst(StaticInstPtr &_staticInst)
: staticInst(_staticInst), traceData(NULL)
{
initVars();
@@ -113,7 +114,7 @@ BaseDynInst<Impl>::initVars()
asid = 0;
// Initialize the fault to be unimplemented opcode.
- fault = Unimplemented_Opcode_Fault;
+ fault = new UnimplementedOpcodeFault;
++instcount;
@@ -138,16 +139,16 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
// state.
// Generate a MemReq so we can translate the effective address.
- MemReqPtr req = new MemReq(addr, xc, 1, flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), 1, 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 = cpuXC->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
@@ -183,12 +184,12 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
// will casue a TLB miss trap if necessary... not sure whether
// that's the best thing to do or not. We don't really need the
// MemReq otherwise, since wh64 has no functional effect.
- MemReqPtr req = new MemReq(addr, xc, size, flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), size, flags);
req->asid = asid;
- fault = xc->translateDataWriteReq(req);
+ fault = cpuXC->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).
@@ -211,18 +212,18 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copySrcTranslate(Addr src)
{
- MemReqPtr req = new MemReq(src, xc, 64);
+ MemReqPtr req = new MemReq(src, cpuXC->getProxy(), 64);
req->asid = asid;
// translate to physical address
- Fault fault = xc->translateDataReadReq(req);
+ Fault fault = cpuXC->translateDataReadReq(req);
- if (fault == No_Fault) {
- xc->copySrcAddr = src;
- xc->copySrcPhysAddr = req->paddr;
+ if (fault == NoFault) {
+ cpuXC->copySrcAddr = src;
+ cpuXC->copySrcPhysAddr = req->paddr;
} else {
- xc->copySrcAddr = 0;
- xc->copySrcPhysAddr = 0;
+ cpuXC->copySrcAddr = 0;
+ cpuXC->copySrcPhysAddr = 0;
}
return fault;
}
@@ -235,18 +236,18 @@ Fault
BaseDynInst<Impl>::copy(Addr dest)
{
uint8_t data[64];
- FunctionalMemory *mem = xc->mem;
- assert(xc->copySrcPhysAddr || xc->misspeculating());
- MemReqPtr req = new MemReq(dest, xc, 64);
+ FunctionalMemory *mem = cpuXC->mem;
+ assert(cpuXC->copySrcPhysAddr || cpuXC->misspeculating());
+ MemReqPtr req = new MemReq(dest, cpuXC->getProxy(), 64);
req->asid = asid;
// translate to physical address
- Fault fault = xc->translateDataWriteReq(req);
+ Fault fault = cpuXC->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;
+ req->paddr = cpuXC->copySrcPhysAddr;
mem->read(req, data);
req->paddr = dest_addr;
mem->write(req, data);
@@ -292,7 +293,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 +304,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 +326,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
break;
default:
- fault = Machine_Check_Fault;
+ fault = genMachineCheckFault();
break;
}
diff --git a/cpu/base_dyn_inst.hh b/cpu/base_dyn_inst.hh
index d29257a52..3a7852f79 100644
--- a/cpu/base_dyn_inst.hh
+++ b/cpu/base_dyn_inst.hh
@@ -51,7 +51,6 @@
*/
// Forward declaration.
-template <class ISA>
class StaticInstPtr;
template <class Impl>
@@ -61,25 +60,20 @@ class BaseDynInst : public FastAlloc, public RefCounted
// Typedef for the CPU.
typedef typename Impl::FullCPU FullCPU;
- //Typedef to get the ISA.
- typedef typename Impl::ISA ISA;
-
/// Binary machine instruction type.
- typedef typename ISA::MachInst MachInst;
- /// Memory address type.
- typedef typename ISA::Addr Addr;
+ typedef TheISA::MachInst MachInst;
/// Logical register index type.
- typedef typename ISA::RegIndex RegIndex;
+ typedef TheISA::RegIndex RegIndex;
/// Integer register index type.
- typedef typename ISA::IntReg IntReg;
+ typedef TheISA::IntReg IntReg;
enum {
- MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
};
/** The static inst used by this dyn inst. */
- StaticInstPtr<ISA> staticInst;
+ StaticInstPtr staticInst;
////////////////////////////////////////////
//
@@ -151,7 +145,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
FullCPU *cpu;
/** Pointer to the exec context. Will not exist in the final version. */
- ExecContext *xc;
+ CPUExecContext *cpuXC;
/** The kind of fault this instruction has generated. */
Fault fault;
@@ -214,7 +208,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
FullCPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
- BaseDynInst(StaticInstPtr<ISA> &_staticInst);
+ BaseDynInst(StaticInstPtr &_staticInst);
/** BaseDynInst destructor. */
~BaseDynInst();
@@ -412,7 +406,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns the exec context.
* @todo: Remove this once the ExecContext is no longer used.
*/
- ExecContext *xcBase() { return xc; }
+ ExecContext *xcBase() { return cpuXC->getProxy(); }
private:
/** Instruction effective address.
@@ -450,7 +444,7 @@ template<class T>
inline Fault
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
{
- MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
req->asid = asid;
fault = cpu->translateDataReadReq(req);
@@ -472,7 +466,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
req->paddr = req->vaddr;
#endif
- if (fault == No_Fault) {
+ if (fault == NoFault) {
fault = cpu->read(req, data, lqIdx);
} else {
// Return a fixed value to keep simulation deterministic even
@@ -498,7 +492,7 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
traceData->setData(data);
}
- MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
req->asid = asid;
@@ -520,14 +514,14 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
req->paddr = req->vaddr;
#endif
- if (fault == No_Fault) {
+ if (fault == NoFault) {
fault = cpu->write(req, data, sqIdx);
}
if (res) {
// always return some result to keep misspeculated paths
// (which will ignore faults) deterministic
- *res = (fault == No_Fault) ? req->result : 0;
+ *res = (fault == NoFault) ? req->result : 0;
}
return fault;
diff --git a/cpu/exec_context.cc b/cpu/cpu_exec_context.cc
index 0b91992cf..6ef42762d 100644
--- a/cpu/exec_context.cc
+++ b/cpu/cpu_exec_context.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,18 +29,20 @@
#include <string>
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#if FULL_SYSTEM
#include "base/callback.hh"
#include "base/cprintf.hh"
#include "base/output.hh"
+#include "base/trace.hh"
#include "cpu/profile.hh"
#include "kern/kernel_stats.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
-#include "targetarch/stacktrace.hh"
+#include "arch/stacktrace.hh"
#else
#include "sim/process.hh"
#include "mem/translating_port.hh"
@@ -50,23 +52,23 @@ using namespace std;
// constructor
#if FULL_SYSTEM
-ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
+CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
AlphaITB *_itb, AlphaDTB *_dtb,
Memory *_mem)
: _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
- cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
- memctrl(_sys->memctrl), physmem(_sys->physmem),
- kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
- fnbin(kernelBinning->fnbin), profile(NULL),
- func_exe_inst(0), storeCondFailures(0)
+ cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb),
+ dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem),
+ profile(NULL), quiesceEvent(this), func_exe_inst(0), storeCondFailures(0)
{
- kernelStats = new Kernel::Statistics(this);
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+
memset(&regs, 0, sizeof(RegFile));
if (cpu->params->profile) {
profile = new FunctionProfile(system->kernelSymtab);
Callback *cb =
- new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
+ new MakeCallback<CPUExecContext,
+ &CPUExecContext::dumpFuncProfile>(this);
registerExitCallback(cb);
}
@@ -77,59 +79,99 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
profilePC = 3;
}
#else
-ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
+CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
Process *_process, int _asid, Port *mem_port)
: _status(ExecContext::Unallocated),
- cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
- process(_process),
- asid(_asid),
+ cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
+ lastSuspend(0), process(_process), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
port = new TranslatingPort(mem_port, process->pTable);
memset(&regs, 0, sizeof(RegFile));
+ proxy = new ProxyExecContext<CPUExecContext>(this);
}
-#endif
-ExecContext::~ExecContext()
+CPUExecContext::CPUExecContext(RegFile *regFile)
+ : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1),
+ func_exe_inst(0), storeCondFailures(0)
{
-#if FULL_SYSTEM
- delete kernelStats;
+ regs = *regFile;
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+}
+
#endif
+
+CPUExecContext::~CPUExecContext()
+{
+ delete proxy;
}
#if FULL_SYSTEM
void
-ExecContext::dumpFuncProfile()
+CPUExecContext::dumpFuncProfile()
{
std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
- profile->dump(this, *os);
+ profile->dump(proxy, *os);
+}
+
+CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC)
+ : Event(&mainEventQueue), cpuXC(_cpuXC)
+{
+}
+
+void
+CPUExecContext::EndQuiesceEvent::process()
+{
+ cpuXC->activate();
}
+
+const char*
+CPUExecContext::EndQuiesceEvent::description()
+{
+ return "End Quiesce Event.";
+}
+
+void
+CPUExecContext::profileClear()
+{
+ if (profile)
+ profile->clear();
+}
+
+void
+CPUExecContext::profileSample()
+{
+ if (profile)
+ profile->sample(profileNode, profilePC);
+}
+
#endif
void
-ExecContext::takeOverFrom(ExecContext *oldContext)
+CPUExecContext::takeOverFrom(ExecContext *oldContext)
{
// some things should already be set up
-// assert(mem == oldContext->mem);
#if FULL_SYSTEM
- assert(system == oldContext->system);
+ assert(system == oldContext->getSystemPtr());
#else
- assert(process == oldContext->process);
+ assert(process == oldContext->getProcessPtr());
#endif
// copy over functional state
- _status = oldContext->_status;
- regs = oldContext->regs;
- cpu_id = oldContext->cpu_id;
- func_exe_inst = oldContext->func_exe_inst;
+ _status = oldContext->status();
+ copyArchRegs(oldContext);
+ cpu_id = oldContext->readCpuId();
+#if !FULL_SYSTEM
+ func_exe_inst = oldContext->readFuncExeInst();
+#endif
storeCondFailures = 0;
- oldContext->_status = ExecContext::Unallocated;
+ oldContext->setStatus(ExecContext::Unallocated);
}
void
-ExecContext::serialize(ostream &os)
+CPUExecContext::serialize(ostream &os)
{
SERIALIZE_ENUM(_status);
regs.serialize(os);
@@ -138,13 +180,17 @@ ExecContext::serialize(ostream &os)
SERIALIZE_SCALAR(inst);
#if FULL_SYSTEM
- kernelStats->serialize(os);
+ Tick quiesceEndTick = 0;
+ if (quiesceEvent.scheduled())
+ quiesceEndTick = quiesceEvent.when();
+ SERIALIZE_SCALAR(quiesceEndTick);
+
#endif
}
void
-ExecContext::unserialize(Checkpoint *cp, const std::string &section)
+CPUExecContext::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ENUM(_status);
regs.unserialize(cp, section);
@@ -153,77 +199,92 @@ ExecContext::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(inst);
#if FULL_SYSTEM
- kernelStats->unserialize(cp, section);
+ Tick quiesceEndTick;
+ UNSERIALIZE_SCALAR(quiesceEndTick);
+ if (quiesceEndTick)
+ quiesceEvent.schedule(quiesceEndTick);
#endif
}
void
-ExecContext::activate(int delay)
+CPUExecContext::activate(int delay)
{
- if (status() == Active)
+ if (status() == ExecContext::Active)
return;
- _status = Active;
+ lastActivate = curTick;
+
+ _status = ExecContext::Active;
cpu->activateContext(thread_num, delay);
}
void
-ExecContext::suspend()
+CPUExecContext::suspend()
{
- if (status() == Suspended)
+ if (status() == ExecContext::Suspended)
return;
+ lastActivate = curTick;
+ lastSuspend = curTick;
+/*
#if FULL_SYSTEM
// Don't change the status from active if there are pending interrupts
if (cpu->check_interrupts()) {
- assert(status() == Active);
+ assert(status() == ExecContext::Active);
return;
}
#endif
-
- _status = Suspended;
+*/
+ _status = ExecContext::Suspended;
cpu->suspendContext(thread_num);
}
void
-ExecContext::deallocate()
+CPUExecContext::deallocate()
{
- if (status() == Unallocated)
+ if (status() == ExecContext::Unallocated)
return;
- _status = Unallocated;
+ _status = ExecContext::Unallocated;
cpu->deallocateContext(thread_num);
}
void
-ExecContext::halt()
+CPUExecContext::halt()
{
- if (status() == Halted)
+ if (status() == ExecContext::Halted)
return;
- _status = Halted;
+ _status = ExecContext::Halted;
cpu->haltContext(thread_num);
}
void
-ExecContext::regStats(const string &name)
+CPUExecContext::regStats(const string &name)
{
-#if FULL_SYSTEM
- kernelStats->regStats(name + ".kern");
-#endif
}
void
-ExecContext::trap(Fault fault)
+CPUExecContext::copyArchRegs(ExecContext *xc)
{
- //TheISA::trap(fault); //One possible way to do it...
+ // First loop through the integer registers.
+ for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
+ setIntReg(i, xc->readIntReg(i));
+ }
- /** @todo: Going to hack it for now. Do a true fixup later. */
-#if FULL_SYSTEM
- ev5_trap(fault);
-#else
- fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());
-#endif
+ // Then loop through the floating point registers.
+ for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
+ setFloatRegDouble(i, xc->readFloatRegDouble(i));
+ setFloatRegInt(i, xc->readFloatRegInt(i));
+ }
+
+ // Copy misc. registers
+ regs.miscRegs.copyMiscRegs(xc);
+
+ // Lastly copy PC/NPC
+ setPC(xc->readPC());
+ setNextPC(xc->readNextPC());
}
+
diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh
new file mode 100644
index 000000000..e17cfbb94
--- /dev/null
+++ b/cpu/cpu_exec_context.hh
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
+#define __CPU_CPU_EXEC_CONTEXT_HH__
+
+#include "arch/isa_traits.hh"
+#include "config/full_system.hh"
+#include "cpu/exec_context.hh"
+#include "mem/physical.hh"
+#include "mem/request.hh"
+#include "sim/byteswap.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+
+class BaseCPU;
+
+#if FULL_SYSTEM
+
+#include "sim/system.hh"
+#include "arch/tlb.hh"
+
+class FunctionProfile;
+class ProfileNode;
+class MemoryController;
+
+#else // !FULL_SYSTEM
+
+#include "sim/process.hh"
+class TranslatingPort;
+
+#endif // FULL_SYSTEM
+
+//
+// The CPUExecContext object represents a functional context for
+// instruction execution. It incorporates everything required for
+// architecture-level functional simulation of a single thread.
+//
+
+class CPUExecContext
+{
+ protected:
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MachInst MachInst;
+ typedef TheISA::MiscRegFile MiscRegFile;
+ typedef TheISA::MiscReg MiscReg;
+ public:
+ typedef ExecContext::Status Status;
+
+ private:
+ Status _status;
+
+ public:
+ Status status() const { return _status; }
+
+ void setStatus(Status newStatus) { _status = newStatus; }
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1);
+
+ /// Set the status to Suspended.
+ void suspend();
+
+ /// Set the status to Unallocated.
+ void deallocate();
+
+ /// Set the status to Halted.
+ void halt();
+
+ protected:
+ RegFile regs; // correct-path register context
+
+ public:
+ // pointer to CPU associated with this context
+ BaseCPU *cpu;
+
+ ProxyExecContext<CPUExecContext> *proxy;
+
+ // Current instruction
+ MachInst inst;
+
+ // Index of hardware thread context on the CPU that this represents.
+ int thread_num;
+
+ // ID of this context w.r.t. the System or Process object to which
+ // it belongs. For full-system mode, this is the system CPU ID.
+ int cpu_id;
+
+ Tick lastActivate;
+ Tick lastSuspend;
+
+ System *system;
+
+ /// Port that syscalls can use to access memory (provides translation step).
+ TranslatingPort *port;
+// Memory *mem;
+
+#if FULL_SYSTEM
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+
+ // the following two fields are redundant, since we can always
+ // look them up through the system pointer, but we'll leave them
+ // here for now for convenience
+ MemoryController *memctrl;
+// PhysicalMemory *physmem;
+
+ FunctionProfile *profile;
+ ProfileNode *profileNode;
+ Addr profilePC;
+ void dumpFuncProfile();
+
+ /** Event for timing out quiesce instruction */
+ struct EndQuiesceEvent : public Event
+ {
+ /** A pointer to the execution context that is quiesced */
+ CPUExecContext *cpuXC;
+
+ EndQuiesceEvent(CPUExecContext *_cpuXC);
+
+ /** Event process to occur at interrupt*/
+ virtual void process();
+
+ /** Event description */
+ virtual const char *description();
+ };
+ EndQuiesceEvent quiesceEvent;
+
+ Event *getQuiesceEvent() { return &quiesceEvent; }
+
+ Tick readLastActivate() { return lastActivate; }
+
+ Tick readLastSuspend() { return lastSuspend; }
+
+ void profileClear();
+
+ void profileSample();
+
+#else
+ Process *process;
+
+ // Address space ID. Note that this is used for TIMING cache
+ // simulation only; all functional memory accesses should use
+ // one of the FunctionalMemory pointers above.
+ short asid;
+
+#endif
+
+ /**
+ * Temporary storage to pass the source address from copy_load to
+ * copy_store.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcAddr;
+ /**
+ * Temp storage for the physical source address of a copy.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcPhysAddr;
+
+
+ /*
+ * number of executed instructions, for matching with syscall trace
+ * points in EIO files.
+ */
+ Counter func_exe_inst;
+
+ //
+ // Count failed store conditionals so we can warn of apparent
+ // application deadlock situations.
+ unsigned storeCondFailures;
+
+ // constructor: initialize context from given process structure
+#if FULL_SYSTEM
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
+ AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
+#else
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port);
+ // Constructor to use XC to pass reg file around. Not used for anything
+ // else.
+ CPUExecContext(RegFile *regFile);
+#endif
+ virtual ~CPUExecContext();
+
+ virtual void takeOverFrom(ExecContext *oldContext);
+
+ void regStats(const std::string &name);
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ BaseCPU *getCpuPtr() { return cpu; }
+
+ ExecContext *getProxy() { return proxy; }
+
+ int getThreadNum() { return thread_num; }
+
+#if FULL_SYSTEM
+ System *getSystemPtr() { return system; }
+
+ PhysicalMemory *getPhysMemPtr() { return physmem; }
+
+ AlphaITB *getITBPtr() { return itb; }
+
+ AlphaDTB *getDTBPtr() { return dtb; }
+
+ bool validInstAddr(Addr addr) { return true; }
+ bool validDataAddr(Addr addr) { return true; }
+ int getInstAsid() { return regs.instAsid(); }
+ int getDataAsid() { return regs.dataAsid(); }
+
+ Fault translateInstReq(CpuRequestPtr &req)
+ {
+ return itb->translate(req);
+ }
+
+ Fault translateDataReadReq(CpuRequestPtr &req)
+ {
+ return dtb->translate(req, false);
+ }
+
+ Fault translateDataWriteReq(CpuRequestPtr &req)
+ {
+ return dtb->translate(req, true);
+ }
+
+#else
+ Process *getProcessPtr() { return process; }
+
+ bool validInstAddr(Addr addr)
+ { return process->validInstAddr(addr); }
+
+ bool validDataAddr(Addr addr)
+ { return process->validDataAddr(addr); }
+
+ int getInstAsid() { return asid; }
+ int getDataAsid() { return asid; }
+
+ Fault translateInstReq(CpuRequestPtr &req)
+ {
+ return process->pTable->translate(req);
+ }
+
+ Fault translateDataReadReq(CpuRequestPtr &req)
+ {
+ return process->pTable->translate(req);
+ }
+
+ Fault translateDataWriteReq(CpuRequestPtr &req)
+ {
+ return process->pTable->translate(req);
+ }
+
+#endif
+
+/*
+ template <class T>
+ Fault read(CpuRequestPtr &req, T &data)
+ {
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
+ if (req->flags & LOCKED) {
+ req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
+ req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
+ }
+#endif
+
+ Fault error;
+ error = mem->prot_read(req->paddr, data, req->size);
+ data = LittleEndianGuest::gtoh(data);
+ return error;
+ }
+
+ template <class T>
+ Fault write(CpuRequestPtr &req, T &data)
+ {
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
+ ExecContext *xc;
+
+ // If this is a store conditional, act appropriately
+ if (req->flags & LOCKED) {
+ xc = req->xc;
+
+ if (req->flags & UNCACHEABLE) {
+ // Don't update result register (see stq_c in isa_desc)
+ req->result = 2;
+ xc->setStCondFailures(0);//Needed? [RGD]
+ } else {
+ bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
+ Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
+ req->result = lock_flag;
+ if (!lock_flag ||
+ ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setStCondFailures(xc->readStCondFailures() + 1);
+ if (((xc->readStCondFailures()) % 100000) == 0) {
+ std::cerr << "Warning: "
+ << xc->readStCondFailures()
+ << " consecutive store conditional failures "
+ << "on cpu " << req->xc->readCpuId()
+ << std::endl;
+ }
+ return NoFault;
+ }
+ else xc->setStCondFailures(0);
+ }
+ }
+
+ // Need to clear any locked flags on other proccessors for
+ // this address. Only do this for succsful Store Conditionals
+ // and all other stores (WH64?). Unsuccessful Store
+ // Conditionals would have returned above, and wouldn't fall
+ // through.
+ for (int i = 0; i < system->execContexts.size(); i++){
+ xc = system->execContexts[i];
+ if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
+ (req->paddr & ~0xf)) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ }
+ }
+
+#endif
+ return mem->prot_write(req->paddr, (T)htog(data), req->size);
+ }
+*/
+ virtual bool misspeculating();
+
+
+ MachInst getInst() { return inst; }
+
+ void setInst(MachInst new_inst)
+ {
+ inst = new_inst;
+ }
+
+ Fault instRead(CpuRequestPtr &req)
+ {
+ panic("instRead not implemented");
+ // return funcPhysMem->read(req, inst);
+ return No_Fault;
+ }
+
+ void setCpuId(int id) { cpu_id = id; }
+
+ int readCpuId() { return cpu_id; }
+
+ FunctionalMemory *getMemPtr() { return mem; }
+
+ void copyArchRegs(ExecContext *xc);
+
+ //
+ // New accessors for new decoder.
+ //
+ uint64_t readIntReg(int reg_idx)
+ {
+ return regs.intRegFile[reg_idx];
+ }
+
+ float readFloatRegSingle(int reg_idx)
+ {
+ return (float)regs.floatRegFile.d[reg_idx];
+ }
+
+ double readFloatRegDouble(int reg_idx)
+ {
+ return regs.floatRegFile.d[reg_idx];
+ }
+
+ uint64_t readFloatRegInt(int reg_idx)
+ {
+ return regs.floatRegFile.q[reg_idx];
+ }
+
+ void setIntReg(int reg_idx, uint64_t val)
+ {
+ regs.intRegFile[reg_idx] = val;
+ }
+
+ void setFloatRegSingle(int reg_idx, float val)
+ {
+ regs.floatRegFile.d[reg_idx] = (double)val;
+ }
+
+ void setFloatRegDouble(int reg_idx, double val)
+ {
+ regs.floatRegFile.d[reg_idx] = val;
+ }
+
+ void setFloatRegInt(int reg_idx, uint64_t val)
+ {
+ regs.floatRegFile.q[reg_idx] = val;
+ }
+
+ uint64_t readPC()
+ {
+ return regs.pc;
+ }
+
+ void setPC(uint64_t val)
+ {
+ regs.pc = val;
+ }
+
+ uint64_t readNextPC()
+ {
+ return regs.npc;
+ }
+
+ void setNextPC(uint64_t val)
+ {
+ regs.npc = val;
+ }
+
+ uint64_t readNextNPC()
+ {
+ return regs.nnpc;
+ }
+
+ void setNextNPC(uint64_t val)
+ {
+ regs.nnpc = val;
+ }
+
+
+ MiscReg readMiscReg(int misc_reg)
+ {
+ return regs.miscRegs.readReg(misc_reg);
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
+ }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ return regs.miscRegs.setReg(misc_reg, val);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy);
+ }
+
+ unsigned readStCondFailures() { return storeCondFailures; }
+
+ void setStCondFailures(unsigned sc_failures)
+ { storeCondFailures = sc_failures; }
+
+ void clearArchRegs() { memset(&regs, 0, sizeof(regs)); }
+
+#if FULL_SYSTEM
+ int readIntrFlag() { return regs.intrflag; }
+ void setIntrFlag(int val) { regs.intrflag = val; }
+ Fault hwrei();
+ bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
+ bool simPalCheck(int palFunc);
+#endif
+
+#if !FULL_SYSTEM
+ TheISA::IntReg getSyscallArg(int i)
+ {
+ return regs.intRegFile[TheISA::ArgumentReg0 + i];
+ }
+
+ // used to shift args for indirect syscall
+ void setSyscallArg(int i, TheISA::IntReg val)
+ {
+ regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
+ }
+
+ void setSyscallReturn(SyscallReturn return_value)
+ {
+ TheISA::setSyscallReturn(return_value, &regs);
+ }
+
+ void syscall()
+ {
+ process->syscall(proxy);
+ }
+
+ Counter readFuncExeInst() { return func_exe_inst; }
+
+ void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
+#endif
+};
+
+
+// for non-speculative execution context, spec_mode is always false
+inline bool
+CPUExecContext::misspeculating()
+{
+ return false;
+}
+
+#endif // __CPU_CPU_EXEC_CONTEXT_HH__
diff --git a/cpu/cpu_models.py b/cpu/cpu_models.py
new file mode 100644
index 000000000..675204e5b
--- /dev/null
+++ b/cpu/cpu_models.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2003-2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+################
+# CpuModel class
+#
+# The CpuModel class encapsulates everything the ISA parser needs to
+# know about a particular CPU model.
+
+class CpuModel:
+ # Dict of available CPU model objects. Accessible as CpuModel.dict.
+ dict = {}
+
+ # Constructor. Automatically adds models to CpuModel.dict.
+ def __init__(self, name, filename, includes, strings):
+ self.name = name
+ self.filename = filename # filename for output exec code
+ self.includes = includes # include files needed in exec file
+ # The 'strings' dict holds all the per-CPU symbols we can
+ # substitute into templates etc.
+ self.strings = strings
+ # Add self to dict
+ CpuModel.dict[name] = self
+
+
+#
+# Define CPU models.
+#
+# Parameters are:
+# - name of model
+# - filename for generated ISA execution file
+# - includes needed for generated ISA execution file
+# - substitution strings for ISA description templates
+#
+
+CpuModel('SimpleCPU', 'simple_cpu_exec.cc',
+ '#include "cpu/simple/cpu.hh"',
+ { 'CPU_exec_context': 'SimpleCPU' })
+CpuModel('FastCPU', 'fast_cpu_exec.cc',
+ '#include "cpu/fast/cpu.hh"',
+ { 'CPU_exec_context': 'FastCPU' })
+CpuModel('FullCPU', 'full_cpu_exec.cc',
+ '#include "encumbered/cpu/full/dyn_inst.hh"',
+ { 'CPU_exec_context': 'DynInst' })
+CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
+ '#include "cpu/o3/alpha_dyn_inst.hh"',
+ { 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
+
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index f55b45de1..2b6c41bd7 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,39 +30,32 @@
#define __CPU_EXEC_CONTEXT_HH__
#include "config/full_system.hh"
-#include "mem/physical.hh"
-#include "mem/request.hh"
+#include "mem/mem_req.hh"
+#include "sim/faults.hh"
#include "sim/host.hh"
#include "sim/serialize.hh"
-#include "targetarch/byte_swap.hh"
+#include "sim/byteswap.hh"
+// forward declaration: see functional_memory.hh
+// @todo: Figure out a more architecture independent way to obtain the ITB and
+// DTB pointers.
+class AlphaDTB;
+class AlphaITB;
class BaseCPU;
-
-#if FULL_SYSTEM
-
-#include "sim/system.hh"
-#include "targetarch/alpha_memory.hh"
-
-class FunctionProfile;
-class ProfileNode;
-class MemoryController;
-namespace Kernel { class Binning; class Statistics; }
-
-#else // !FULL_SYSTEM
-
-#include "sim/process.hh"
-class TranslatingPort;
-
-#endif // FULL_SYSTEM
-
-//
-// The ExecContext object represents a functional context for
-// instruction execution. It incorporates everything required for
-// architecture-level functional simulation of a single thread.
-//
+class Event;
+class FunctionalMemory;
+class PhysicalMemory;
+class Process;
+class System;
class ExecContext
{
+ protected:
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MachInst MachInst;
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::MiscRegFile MiscRegFile;
+ typedef TheISA::MiscReg MiscReg;
public:
enum Status
{
@@ -86,384 +79,339 @@ class ExecContext
Halted
};
- private:
- Status _status;
+ virtual ~ExecContext() { };
- public:
- Status status() const { return _status; }
+ virtual BaseCPU *getCpuPtr() = 0;
+
+ virtual void setCpuId(int id) = 0;
+
+ virtual int readCpuId() = 0;
+
+ virtual FunctionalMemory *getMemPtr() = 0;
+
+#if FULL_SYSTEM
+ virtual System *getSystemPtr() = 0;
+
+ virtual PhysicalMemory *getPhysMemPtr() = 0;
+
+ virtual AlphaITB *getITBPtr() = 0;
+
+ virtual AlphaDTB * getDTBPtr() = 0;
+#else
+ virtual Process *getProcessPtr() = 0;
+#endif
+
+ virtual Status status() const = 0;
+
+ virtual void setStatus(Status new_status) = 0;
/// Set the status to Active. Optional delay indicates number of
/// cycles to wait before beginning execution.
- void activate(int delay = 1);
+ virtual void activate(int delay = 1) = 0;
/// Set the status to Suspended.
- void suspend();
+ virtual void suspend() = 0;
/// Set the status to Unallocated.
- void deallocate();
+ virtual void deallocate() = 0;
/// Set the status to Halted.
- void halt();
+ virtual void halt() = 0;
- public:
- RegFile regs; // correct-path register context
+#if FULL_SYSTEM
+ virtual void dumpFuncProfile() = 0;
+#endif
- // pointer to CPU associated with this context
- BaseCPU *cpu;
+ virtual void takeOverFrom(ExecContext *old_context) = 0;
- // Current instruction
- MachInst inst;
+ virtual void regStats(const std::string &name) = 0;
- // Index of hardware thread context on the CPU that this represents.
- int thread_num;
+ virtual void serialize(std::ostream &os) = 0;
+ virtual void unserialize(Checkpoint *cp, const std::string &section) = 0;
- // ID of this context w.r.t. the System or Process object to which
- // it belongs. For full-system mode, this is the system CPU ID.
- int cpu_id;
+#if FULL_SYSTEM
+ virtual Event *getQuiesceEvent() = 0;
- System *system;
+ // Not necessarily the best location for these...
+ // Having an extra function just to read these is obnoxious
+ virtual Tick readLastActivate() = 0;
+ virtual Tick readLastSuspend() = 0;
- /// Port that syscalls can use to access memory (provides translation step).
- TranslatingPort *port;
-// Memory *mem;
+ virtual void profileClear() = 0;
+ virtual void profileSample() = 0;
+#endif
-#if FULL_SYSTEM
- AlphaITB *itb;
- AlphaDTB *dtb;
+ virtual int getThreadNum() = 0;
- // the following two fields are redundant, since we can always
- // look them up through the system pointer, but we'll leave them
- // here for now for convenience
- MemoryController *memctrl;
-// PhysicalMemory *physmem;
+ virtual bool validInstAddr(Addr addr) = 0;
+ virtual bool validDataAddr(Addr addr) = 0;
+ virtual int getInstAsid() = 0;
+ virtual int getDataAsid() = 0;
- Kernel::Binning *kernelBinning;
- Kernel::Statistics *kernelStats;
- bool bin;
- bool fnbin;
+ virtual Fault translateInstReq(MemReqPtr &req) = 0;
- FunctionProfile *profile;
- ProfileNode *profileNode;
- Addr profilePC;
- void dumpFuncProfile();
+ virtual Fault translateDataReadReq(MemReqPtr &req) = 0;
-#else
- Process *process;
+ virtual Fault translateDataWriteReq(MemReqPtr &req) = 0;
- // Address space ID. Note that this is used for TIMING cache
- // simulation only; all functional memory accesses should use
- // one of the FunctionalMemory pointers above.
- short asid;
+ // Also somewhat obnoxious. Really only used for the TLB fault.
+ // However, may be quite useful in SPARC.
+ virtual TheISA::MachInst getInst() = 0;
-#endif
+ virtual void copyArchRegs(ExecContext *xc) = 0;
- /**
- * Temporary storage to pass the source address from copy_load to
- * copy_store.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcAddr;
- /**
- * Temp storage for the physical source address of a copy.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcPhysAddr;
-
-
- /*
- * number of executed instructions, for matching with syscall trace
- * points in EIO files.
- */
- Counter func_exe_inst;
+ virtual void clearArchRegs() = 0;
//
- // Count failed store conditionals so we can warn of apparent
- // application deadlock situations.
- unsigned storeCondFailures;
+ // New accessors for new decoder.
+ //
+ virtual uint64_t readIntReg(int reg_idx) = 0;
+
+ virtual float readFloatRegSingle(int reg_idx) = 0;
+
+ virtual double readFloatRegDouble(int reg_idx) = 0;
+
+ virtual uint64_t readFloatRegInt(int reg_idx) = 0;
+
+ virtual void setIntReg(int reg_idx, uint64_t val) = 0;
+
+ virtual void setFloatRegSingle(int reg_idx, float val) = 0;
+
+ virtual void setFloatRegDouble(int reg_idx, double val) = 0;
+
+ virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0;
+
+ virtual uint64_t readPC() = 0;
+
+ virtual void setPC(uint64_t val) = 0;
+
+ virtual uint64_t readNextPC() = 0;
+
+ virtual void setNextPC(uint64_t val) = 0;
+
+ virtual MiscReg readMiscReg(int misc_reg) = 0;
+
+ virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0;
+
+ virtual Fault setMiscReg(int misc_reg, const MiscReg &val) = 0;
+
+ virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0;
+
+ // Also not necessarily the best location for these two. Hopefully will go
+ // away once we decide upon where st cond failures goes.
+ virtual unsigned readStCondFailures() = 0;
+
+ virtual void setStCondFailures(unsigned sc_failures) = 0;
- // constructor: initialize context from given process structure
#if FULL_SYSTEM
- ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
-#else
- ExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid, Port *mem_port);
+ virtual int readIntrFlag() = 0;
+ virtual void setIntrFlag(int val) = 0;
+ virtual Fault hwrei() = 0;
+ virtual bool inPalMode() = 0;
+ virtual bool simPalCheck(int palFunc) = 0;
#endif
- virtual ~ExecContext();
- virtual void takeOverFrom(ExecContext *oldContext);
+ // Only really makes sense for old CPU model. Still could be useful though.
+ virtual bool misspeculating() = 0;
- void regStats(const std::string &name);
+#if !FULL_SYSTEM
+ virtual IntReg getSyscallArg(int i) = 0;
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
+ // used to shift args for indirect syscall
+ virtual void setSyscallArg(int i, IntReg val) = 0;
-#if FULL_SYSTEM
- bool validInstAddr(Addr addr) { return true; }
- bool validDataAddr(Addr addr) { return true; }
- int getInstAsid() { return regs.instAsid(); }
- int getDataAsid() { return regs.dataAsid(); }
+ virtual void setSyscallReturn(SyscallReturn return_value) = 0;
- Fault translateInstReq(CpuRequestPtr &req)
- {
- return itb->translate(req);
- }
+ virtual void syscall() = 0;
- Fault translateDataReadReq(CpuRequestPtr &req)
- {
- return dtb->translate(req, false);
- }
+ // Same with st cond failures.
+ virtual Counter readFuncExeInst() = 0;
- Fault translateDataWriteReq(CpuRequestPtr &req)
- {
- return dtb->translate(req, true);
- }
+ virtual void setFuncExeInst(Counter new_val) = 0;
+#endif
+};
-#else
- bool validInstAddr(Addr addr)
- { return process->validInstAddr(addr); }
+template <class XC>
+class ProxyExecContext : public ExecContext
+{
+ public:
+ ProxyExecContext(XC *actual_xc)
+ { actualXC = actual_xc; }
- bool validDataAddr(Addr addr)
- { return process->validDataAddr(addr); }
+ private:
+ XC *actualXC;
- int getInstAsid() { return asid; }
- int getDataAsid() { return asid; }
+ public:
- Fault translateInstReq(CpuRequestPtr &req)
- {
- return process->pTable->translate(req);
- }
+ BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
- Fault translateDataReadReq(CpuRequestPtr &req)
- {
- return process->pTable->translate(req);
- }
+ void setCpuId(int id) { actualXC->setCpuId(id); }
- Fault translateDataWriteReq(CpuRequestPtr &req)
- {
- return process->pTable->translate(req);
- }
+ int readCpuId() { return actualXC->readCpuId(); }
+ FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); }
+
+#if FULL_SYSTEM
+ System *getSystemPtr() { return actualXC->getSystemPtr(); }
+
+ PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); }
+
+ AlphaITB *getITBPtr() { return actualXC->getITBPtr(); }
+
+ AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); }
+#else
+ Process *getProcessPtr() { return actualXC->getProcessPtr(); }
#endif
-/*
- template <class T>
- Fault read(CpuRequestPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- MiscRegFile *cregs = &req->xc->regs.miscRegs;
- cregs->lock_addr = req->paddr;
- cregs->lock_flag = true;
- }
+ Status status() const { return actualXC->status(); }
+
+ void setStatus(Status new_status) { actualXC->setStatus(new_status); }
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1) { actualXC->activate(delay); }
+
+ /// Set the status to Suspended.
+ void suspend() { actualXC->suspend(); }
+
+ /// Set the status to Unallocated.
+ void deallocate() { actualXC->deallocate(); }
+
+ /// Set the status to Halted.
+ void halt() { actualXC->halt(); }
+
+#if FULL_SYSTEM
+ void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
#endif
- Fault error;
- error = mem->prot_read(req->paddr, data, req->size);
- data = gtoh(data);
- return error;
- }
+ void takeOverFrom(ExecContext *oldContext)
+ { actualXC->takeOverFrom(oldContext); }
- template <class T>
- Fault write(CpuRequestPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
-
- MiscRegFile *cregs;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- cregs = &req->xc->regs.miscRegs;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- req->xc->storeCondFailures = 0;//Needed? [RGD]
- } else {
- req->result = cregs->lock_flag;
- if (!cregs->lock_flag ||
- ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- cregs->lock_flag = false;
- if (((++req->xc->storeCondFailures) % 100000) == 0) {
- std::cerr << "Warning: "
- << req->xc->storeCondFailures
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->cpu_id
- << std::endl;
- }
- return No_Fault;
- }
- else req->xc->storeCondFailures = 0;
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < system->execContexts.size(); i++){
- cregs = &system->execContexts[i]->regs.miscRegs;
- if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
- cregs->lock_flag = false;
- }
- }
+ void regStats(const std::string &name) { actualXC->regStats(name); }
+
+ void serialize(std::ostream &os) { actualXC->serialize(os); }
+ void unserialize(Checkpoint *cp, const std::string &section)
+ { actualXC->unserialize(cp, section); }
+
+#if FULL_SYSTEM
+ Event *getQuiesceEvent() { return actualXC->getQuiesceEvent(); }
+
+ Tick readLastActivate() { return actualXC->readLastActivate(); }
+ Tick readLastSuspend() { return actualXC->readLastSuspend(); }
+ void profileClear() { return actualXC->profileClear(); }
+ void profileSample() { return actualXC->profileSample(); }
#endif
- return mem->prot_write(req->paddr, (T)htog(data), req->size);
- }
-*/
- virtual bool misspeculating();
+ int getThreadNum() { return actualXC->getThreadNum(); }
- MachInst getInst() { return inst; }
+ bool validInstAddr(Addr addr) { return actualXC->validInstAddr(addr); }
+ bool validDataAddr(Addr addr) { return actualXC->validDataAddr(addr); }
+ int getInstAsid() { return actualXC->getInstAsid(); }
+ int getDataAsid() { return actualXC->getDataAsid(); }
- void setInst(MachInst new_inst)
- {
- inst = new_inst;
- }
+ Fault translateInstReq(MemReqPtr &req)
+ { return actualXC->translateInstReq(req); }
- Fault instRead(CpuRequestPtr &req)
- {
- panic("instRead not implemented");
- // return funcPhysMem->read(req, inst);
- return No_Fault;
- }
+ Fault translateDataReadReq(MemReqPtr &req)
+ { return actualXC->translateDataReadReq(req); }
+
+ Fault translateDataWriteReq(MemReqPtr &req)
+ { return actualXC->translateDataWriteReq(req); }
+
+ // @todo: Do I need this?
+ MachInst getInst() { return actualXC->getInst(); }
+
+ // @todo: Do I need this?
+ void copyArchRegs(ExecContext *xc) { actualXC->copyArchRegs(xc); }
+
+ void clearArchRegs() { actualXC->clearArchRegs(); }
//
// New accessors for new decoder.
//
uint64_t readIntReg(int reg_idx)
- {
- return regs.intRegFile[reg_idx];
- }
+ { return actualXC->readIntReg(reg_idx); }
float readFloatRegSingle(int reg_idx)
- {
- return (float)regs.floatRegFile.d[reg_idx];
- }
+ { return actualXC->readFloatRegSingle(reg_idx); }
double readFloatRegDouble(int reg_idx)
- {
- return regs.floatRegFile.d[reg_idx];
- }
+ { return actualXC->readFloatRegDouble(reg_idx); }
uint64_t readFloatRegInt(int reg_idx)
- {
- return regs.floatRegFile.q[reg_idx];
- }
+ { return actualXC->readFloatRegInt(reg_idx); }
void setIntReg(int reg_idx, uint64_t val)
- {
- regs.intRegFile[reg_idx] = val;
- }
+ { actualXC->setIntReg(reg_idx, val); }
void setFloatRegSingle(int reg_idx, float val)
- {
- regs.floatRegFile.d[reg_idx] = (double)val;
- }
+ { actualXC->setFloatRegSingle(reg_idx, val); }
void setFloatRegDouble(int reg_idx, double val)
- {
- regs.floatRegFile.d[reg_idx] = val;
- }
+ { actualXC->setFloatRegDouble(reg_idx, val); }
void setFloatRegInt(int reg_idx, uint64_t val)
- {
- regs.floatRegFile.q[reg_idx] = val;
- }
+ { actualXC->setFloatRegInt(reg_idx, val); }
- uint64_t readPC()
- {
- return regs.pc;
- }
+ uint64_t readPC() { return actualXC->readPC(); }
- void setNextPC(uint64_t val)
- {
- regs.npc = val;
- }
+ void setPC(uint64_t val) { actualXC->setPC(val); }
- uint64_t readUniq()
- {
- return regs.miscRegs.uniq;
- }
+ uint64_t readNextPC() { return actualXC->readNextPC(); }
- void setUniq(uint64_t val)
- {
- regs.miscRegs.uniq = val;
- }
+ void setNextPC(uint64_t val) { actualXC->setNextPC(val); }
- uint64_t readFpcr()
- {
- return regs.miscRegs.fpcr;
- }
+ MiscReg readMiscReg(int misc_reg)
+ { return actualXC->readMiscReg(misc_reg); }
- void setFpcr(uint64_t val)
- {
- regs.miscRegs.fpcr = val;
- }
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ { return actualXC->setMiscReg(misc_reg, val); }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ { return actualXC->setMiscRegWithEffect(misc_reg, val); }
+
+ unsigned readStCondFailures()
+ { return actualXC->readStCondFailures(); }
+
+ void setStCondFailures(unsigned sc_failures)
+ { actualXC->setStCondFailures(sc_failures); }
#if FULL_SYSTEM
- 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();
- bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
- void ev5_trap(Fault fault);
- bool simPalCheck(int palFunc);
-#endif
+ int readIntrFlag() { return actualXC->readIntrFlag(); }
+
+ void setIntrFlag(int val) { actualXC->setIntrFlag(val); }
+
+ Fault hwrei() { return actualXC->hwrei(); }
+
+ bool inPalMode() { return actualXC->inPalMode(); }
- /** Meant to be more generic trap function to be
- * called when an instruction faults.
- * @param fault The fault generated by executing the instruction.
- * @todo How to do this properly so it's dependent upon ISA only?
- */
+ bool simPalCheck(int palFunc) { return actualXC->simPalCheck(palFunc); }
+#endif
- void trap(Fault fault);
+ // @todo: Fix this!
+ bool misspeculating() { return actualXC->misspeculating(); }
#if !FULL_SYSTEM
- IntReg getSyscallArg(int i)
- {
- return regs.intRegFile[ArgumentReg0 + i];
- }
+ IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
// used to shift args for indirect syscall
void setSyscallArg(int i, IntReg val)
- {
- regs.intRegFile[ArgumentReg0 + i] = val;
- }
+ { actualXC->setSyscallArg(i, val); }
void setSyscallReturn(SyscallReturn return_value)
- {
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- const int RegA3 = 19; // only place this is used
- if (return_value.successful()) {
- // no error
- regs.intRegFile[RegA3] = 0;
- regs.intRegFile[ReturnValueReg] = return_value.value();
- } else {
- // got an error, return details
- regs.intRegFile[RegA3] = (IntReg) -1;
- regs.intRegFile[ReturnValueReg] = -return_value.value();
- }
- }
-
- void syscall()
- {
- process->syscall(this);
- }
-#endif
-};
+ { actualXC->setSyscallReturn(return_value); }
+ void syscall() { actualXC->syscall(); }
-// for non-speculative execution context, spec_mode is always false
-inline bool
-ExecContext::misspeculating()
-{
- return false;
-}
+ Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
-#endif // __CPU_EXEC_CONTEXT_HH__
+ void setFuncExeInst(Counter new_val)
+ { return actualXC->setFuncExeInst(new_val); }
+#endif
+};
+
+#endif
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
index 5c7dc953c..ebb719b2c 100644
--- a/cpu/exetrace.cc
+++ b/cpu/exetrace.cc
@@ -31,7 +31,6 @@
#include "sim/param.hh"
#include "cpu/exetrace.hh"
-#include "cpu/exec_context.hh"
#include "base/loader/symtab.hh"
#include "cpu/base.hh"
#include "cpu/static_inst.hh"
diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh
index 48d8966d8..67d042ec8 100644
--- a/cpu/exetrace.hh
+++ b/cpu/exetrace.hh
@@ -46,13 +46,14 @@ namespace Trace {
class InstRecord : public Record
{
protected:
+ typedef TheISA::IntRegFile IntRegFile;
// The following fields are initialized by the constructor and
// thus guaranteed to be valid.
BaseCPU *cpu;
// need to make this ref-counted so it doesn't go away before we
// dump the record
- StaticInstPtr<TheISA> staticInst;
+ StaticInstPtr staticInst;
Addr PC;
bool misspeculating;
unsigned thread;
@@ -92,7 +93,7 @@ class InstRecord : public Record
public:
InstRecord(Tick _cycle, BaseCPU *_cpu,
- const StaticInstPtr<TheISA> &_staticInst,
+ const StaticInstPtr &_staticInst,
Addr _pc, bool spec, int _thread)
: Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc),
misspeculating(spec), thread(_thread)
@@ -169,7 +170,7 @@ InstRecord::setRegs(const IntRegFile &regs)
inline
InstRecord *
getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu,
- const StaticInstPtr<TheISA> staticInst,
+ const StaticInstPtr staticInst,
Addr pc, int thread = 0)
{
if (DTRACE(InstExec) &&
diff --git a/cpu/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/intr_control.cc b/cpu/intr_control.cc
index 5f17c7212..43e7f654c 100644
--- a/cpu/intr_control.cc
+++ b/cpu/intr_control.cc
@@ -30,6 +30,7 @@
#include <vector>
#include "cpu/base.hh"
+#include "cpu/exec_context.hh"
#include "cpu/intr_control.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
@@ -48,7 +49,7 @@ void
IntrControl::post(int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[0]->cpu;
+ BaseCPU *temp = xcvec[0]->getCpuPtr();
temp->post_interrupt(int_num, index);
}
@@ -56,7 +57,7 @@ void
IntrControl::post(int cpu_id, int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[cpu_id]->cpu;
+ BaseCPU *temp = xcvec[cpu_id]->getCpuPtr();
temp->post_interrupt(int_num, index);
}
@@ -64,7 +65,7 @@ void
IntrControl::clear(int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[0]->cpu;
+ BaseCPU *temp = xcvec[0]->getCpuPtr();
temp->clear_interrupt(int_num, index);
}
@@ -72,7 +73,7 @@ void
IntrControl::clear(int cpu_id, int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[cpu_id]->cpu;
+ BaseCPU *temp = xcvec[cpu_id]->getCpuPtr();
temp->clear_interrupt(int_num, index);
}
diff --git a/cpu/intr_control.hh b/cpu/intr_control.hh
index 2a57a8dfc..5ec4e14cb 100644
--- a/cpu/intr_control.hh
+++ b/cpu/intr_control.hh
@@ -34,7 +34,6 @@
#include "cpu/base.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"
-#include "cpu/exec_context.hh"
class IntrControl : public SimObject
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index 27f790fac..94b66b70b 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -36,7 +36,7 @@
#include "base/misc.hh"
#include "base/statistics.hh"
-#include "cpu/exec_context.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/memtest/memtest.hh"
#include "mem/cache/base_cache.hh"
#include "sim/builder.hh"
@@ -44,6 +44,7 @@
#include "sim/stats.hh"
using namespace std;
+using namespace TheISA;
int TESTER_ALLOCATOR=0;
@@ -78,7 +79,7 @@ MemTest::MemTest(const string &name,
vector<string> cmd;
cmd.push_back("/bin/ls");
vector<string> null_vec;
- xc = new ExecContext(NULL, 0, mainMem, 0);
+ cpuXC = new CPUExecContext(NULL, 0, mainMem, 0);
blockSize = cacheInterface->getBlockSize();
blockAddrMask = blockSize - 1;
@@ -268,7 +269,7 @@ MemTest::tick()
req->data = new uint8_t[req->size];
req->paddr &= ~(req->size - 1);
req->time = curTick;
- req->xc = xc;
+ req->xc = cpuXC->getProxy();
if (cmd < percentReads) {
// read
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
index 7abcf017a..cdb40a26a 100644
--- a/cpu/memtest/memtest.hh
+++ b/cpu/memtest/memtest.hh
@@ -83,7 +83,7 @@ class MemTest : public SimObject
MemInterface *cacheInterface;
FunctionalMemory *mainMem;
FunctionalMemory *checkMem;
- ExecContext *xc;
+ CPUExecContext *cpuXC;
unsigned size; // size of testing memory region
diff --git a/cpu/o3/2bit_local_pred.hh b/cpu/o3/2bit_local_pred.hh
index a97ce455c..97433e542 100644
--- a/cpu/o3/2bit_local_pred.hh
+++ b/cpu/o3/2bit_local_pred.hh
@@ -30,7 +30,7 @@
#define __CPU_O3_CPU_2BIT_LOCAL_PRED_HH__
// For Addr type.
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "cpu/o3/sat_counter.hh"
class DefaultBP
diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh
index cba57d189..0352e9972 100644
--- a/cpu/o3/alpha_cpu.hh
+++ b/cpu/o3/alpha_cpu.hh
@@ -33,12 +33,19 @@
#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>
{
+ protected:
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MiscRegFile MiscRegFile;
+
public:
- typedef typename Impl::ISA AlphaISA;
typedef typename Impl::Params Params;
public:
@@ -85,7 +92,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return No_Fault;
+ return NoFault;
}
Fault translateInstReq(MemReqPtr &req)
@@ -108,33 +115,24 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// Later on may want to remove this misc stuff from the regfile and
// have it handled at this level. Might prove to be an issue when
// trying to rename source/destination registers...
- uint64_t readUniq()
- {
- return this->regFile.readUniq();
- }
-
- void setUniq(uint64_t val)
+ MiscReg readMiscReg(int misc_reg)
{
- this->regFile.setUniq(val);
+ // Dummy function for now.
+ // @todo: Fix this once reg file gets fixed.
+ return 0;
}
- uint64_t readFpcr()
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
{
- return this->regFile.readFpcr();
- }
-
- void setFpcr(uint64_t val)
- {
- this->regFile.setFpcr(val);
+ // Dummy function for now.
+ // @todo: Fix this once reg file gets fixed.
+ return NoFault;
}
// Most of the full system code and syscall emulation is not yet
// implemented. These functions do show what the final interface will
// look like.
#if FULL_SYSTEM
- uint64_t *getIpr();
- uint64_t readIpr(int idx, Fault &fault);
- Fault setIpr(int idx, uint64_t val);
int readIntrFlag();
void setIntrFlag(int val);
Fault hwrei();
@@ -156,13 +154,13 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// set the register.
IntReg getSyscallArg(int i)
{
- return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
+ return this->cpuXC->readIntReg(AlphaISA::ArgumentReg0 + i);
}
// used to shift args for indirect syscall
void setSyscallArg(int i, IntReg val)
{
- this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
+ this->cpuXC->setIntReg(AlphaISA::ArgumentReg0 + i, val);
}
void setSyscallReturn(int64_t return_value)
@@ -173,12 +171,12 @@ class AlphaFullCPU : public FullO3CPU<Impl>
const int RegA3 = 19; // only place this is used
if (return_value >= 0) {
// no error
- this->xc->regs.intRegFile[RegA3] = 0;
- this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
+ this->cpuXC->setIntReg(RegA3, 0);
+ this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, return_value);
} else {
// got an error, return details
- this->xc->regs.intRegFile[RegA3] = (IntReg) -1;
- this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
+ this->cpuXC->setIntReg(RegA3, (IntReg) -1);
+ this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, -return_value);
}
}
@@ -212,9 +210,8 @@ class AlphaFullCPU : public FullO3CPU<Impl>
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
if (req->flags & LOCKED) {
- MiscRegFile *cregs = &req->xc->regs.miscRegs;
- cregs->lock_addr = req->paddr;
- cregs->lock_flag = true;
+ req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
+ req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
}
#endif
@@ -234,32 +231,34 @@ class AlphaFullCPU : public FullO3CPU<Impl>
Fault write(MemReqPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
-
- MiscRegFile *cregs;
+ ExecContext *xc;
// If this is a store conditional, act appropriately
if (req->flags & LOCKED) {
- cregs = &this->xc->regs.miscRegs;
+ xc = req->xc;
if (req->flags & UNCACHEABLE) {
// Don't update result register (see stq_c in isa_desc)
req->result = 2;
- req->xc->storeCondFailures = 0;//Needed? [RGD]
+ xc->setStCondFailures(0);//Needed? [RGD]
} else {
- req->result = cregs->lock_flag;
- if (!cregs->lock_flag ||
- ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- cregs->lock_flag = false;
- if (((++req->xc->storeCondFailures) % 100000) == 0) {
+ bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
+ Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
+ req->result = lock_flag;
+ if (!lock_flag ||
+ ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setStCondFailures(xc->readStCondFailures() + 1);
+ if (((xc->readStCondFailures()) % 100000) == 0) {
std::cerr << "Warning: "
- << req->xc->storeCondFailures
+ << xc->readStCondFailures()
<< " consecutive store conditional failures "
- << "on cpu " << this->cpu_id
+ << "on cpu " << req->xc->readCpuId()
<< std::endl;
}
- return No_Fault;
+ return NoFault;
}
- else req->xc->storeCondFailures = 0;
+ else xc->setStCondFailures(0);
}
}
@@ -269,9 +268,10 @@ class AlphaFullCPU : public FullO3CPU<Impl>
// Conditionals would have returned above, and wouldn't fall
// through.
for (int i = 0; i < this->system->execContexts.size(); i++){
- cregs = &this->system->execContexts[i]->regs.miscRegs;
- if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
- cregs->lock_flag = false;
+ xc = this->system->execContexts[i];
+ if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
+ (req->paddr & ~0xf)) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
}
}
diff --git a/cpu/o3/alpha_cpu_builder.cc b/cpu/o3/alpha_cpu_builder.cc
index 3547fb1b5..6025b8ef2 100644
--- a/cpu/o3/alpha_cpu_builder.cc
+++ b/cpu/o3/alpha_cpu_builder.cc
@@ -30,7 +30,6 @@
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
@@ -50,8 +49,8 @@
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/system.hh"
-#include "targetarch/alpha_memory.hh"
-#include "targetarch/vtophys.hh"
+#include "arch/tlb.hh"
+#include "arch/vtophys.hh"
#else // !FULL_SYSTEM
#include "mem/functional/functional.hh"
#endif // FULL_SYSTEM
diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh
index 2a764740b..9f1fa24f6 100644
--- a/cpu/o3/alpha_cpu_impl.hh
+++ b/cpu/o3/alpha_cpu_impl.hh
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/faults.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
@@ -42,9 +43,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>
@@ -168,7 +166,7 @@ AlphaFullCPU<Impl>::copyToXC()
for (int i = 0; i < AlphaISA::NumIntRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i);
- this->xc->regs.intRegFile[i] = this->regFile.readIntReg(renamed_reg);
+ this->cpuXC->setIntReg(i, this->regFile.readIntReg(renamed_reg));
DPRINTF(FullCPU, "FullCPU: Copying register %i, has data %lli.\n",
renamed_reg, this->regFile.intRegFile[renamed_reg]);
}
@@ -177,21 +175,27 @@ AlphaFullCPU<Impl>::copyToXC()
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
- this->xc->regs.floatRegFile.d[i] =
- this->regFile.readFloatRegDouble(renamed_reg);
- this->xc->regs.floatRegFile.q[i] =
- this->regFile.readFloatRegInt(renamed_reg);
+ this->cpuXC->setFloatRegDouble(i,
+ this->regFile.readFloatRegDouble(renamed_reg));
+ this->cpuXC->setFloatRegInt(i,
+ this->regFile.readFloatRegInt(renamed_reg));
}
- this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs.fpcr;
- this->xc->regs.miscRegs.uniq = this->regFile.miscRegs.uniq;
- this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs.lock_flag;
- this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs.lock_addr;
+ this->cpuXC->setMiscReg(AlphaISA::Fpcr_DepTag,
+ this->regFile.readMiscReg(AlphaISA::Fpcr_DepTag));
+ this->cpuXC->setMiscReg(AlphaISA::Uniq_DepTag,
+ this->regFile.readMiscReg(AlphaISA::Uniq_DepTag));
+ this->cpuXC->setMiscReg(AlphaISA::Lock_Flag_DepTag,
+ this->regFile.readMiscReg(AlphaISA::Lock_Flag_DepTag));
+ this->cpuXC->setMiscReg(AlphaISA::Lock_Addr_DepTag,
+ this->regFile.readMiscReg(AlphaISA::Lock_Addr_DepTag));
- this->xc->regs.pc = this->rob.readHeadPC();
- this->xc->regs.npc = this->xc->regs.pc+4;
+ this->cpuXC->setPC(this->rob.readHeadPC());
+ this->cpuXC->setNextPC(this->cpuXC->readPC()+4);
- this->xc->func_exe_inst = this->funcExeInst;
+#if !FULL_SYSTEM
+ this->cpuXC->setFuncExeInst(this->funcExeInst);
+#endif
}
// This function will probably mess things up unless the ROB is empty and
@@ -210,9 +214,9 @@ AlphaFullCPU<Impl>::copyFromXC()
DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
"now has data %lli.\n",
renamed_reg, this->regFile.intRegFile[renamed_reg],
- this->xc->regs.intRegFile[i]);
+ this->cpuXC->readIntReg(i));
- this->regFile.setIntReg(renamed_reg, this->xc->regs.intRegFile[i]);
+ this->regFile.setIntReg(renamed_reg, this->cpuXC->readIntReg(i));
}
// Then loop through the floating point registers.
@@ -220,48 +224,32 @@ AlphaFullCPU<Impl>::copyFromXC()
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
this->regFile.setFloatRegDouble(renamed_reg,
- this->xc->regs.floatRegFile.d[i]);
+ this->cpuXC->readFloatRegDouble(i));
this->regFile.setFloatRegInt(renamed_reg,
- this->xc->regs.floatRegFile.q[i]);
+ this->cpuXC->readFloatRegInt(i));
}
// Then loop through the misc registers.
- this->regFile.miscRegs.fpcr = this->xc->regs.miscRegs.fpcr;
- this->regFile.miscRegs.uniq = this->xc->regs.miscRegs.uniq;
- this->regFile.miscRegs.lock_flag = this->xc->regs.miscRegs.lock_flag;
- this->regFile.miscRegs.lock_addr = this->xc->regs.miscRegs.lock_addr;
+ this->regFile.setMiscReg(AlphaISA::Fpcr_DepTag,
+ this->cpuXC->readMiscReg(AlphaISA::Fpcr_DepTag));
+ this->regFile.setMiscReg(AlphaISA::Uniq_DepTag,
+ this->cpuXC->readMiscReg(AlphaISA::Uniq_DepTag));
+ this->regFile.setMiscReg(AlphaISA::Lock_Flag_DepTag,
+ this->cpuXC->readMiscReg(AlphaISA::Lock_Flag_DepTag));
+ this->regFile.setMiscReg(AlphaISA::Lock_Addr_DepTag,
+ this->cpuXC->readMiscReg(AlphaISA::Lock_Addr_DepTag));
// Then finally set the PC and the next PC.
-// regFile.pc = xc->regs.pc;
-// regFile.npc = xc->regs.npc;
-
- this->funcExeInst = this->xc->func_exe_inst;
+// regFile.pc = cpuXC->regs.pc;
+// regFile.npc = cpuXC->regs.npc;
+#if !FULL_SYSTEM
+ this->funcExeInst = this->cpuXC->readFuncExeInst();
+#endif
}
#if FULL_SYSTEM
template <class Impl>
-uint64_t *
-AlphaFullCPU<Impl>::getIpr()
-{
- return this->regFile.getIpr();
-}
-
-template <class Impl>
-uint64_t
-AlphaFullCPU<Impl>::readIpr(int idx, Fault &fault)
-{
- return this->regFile.readIpr(idx, fault);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::setIpr(int idx, uint64_t val)
-{
- return this->regFile.setIpr(idx, val);
-}
-
-template <class Impl>
int
AlphaFullCPU<Impl>::readIntrFlag()
{
@@ -280,22 +268,20 @@ template <class Impl>
Fault
AlphaFullCPU<Impl>::hwrei()
{
- uint64_t *ipr = getIpr();
-
if (!inPalMode())
- return Unimplemented_Opcode_Fault;
+ return new AlphaISA::UnimplementedOpcodeFault;
- setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
+ this->setNextPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR));
// kernelStats.hwrei();
- if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
+ if ((this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR) & 1) == 0)
// AlphaISA::swap_palshadow(&regs, false);
this->checkInterrupts = true;
// FIXME: XXX check for interrupts? XXX
- return No_Fault;
+ return NoFault;
}
template <class Impl>
@@ -328,36 +314,38 @@ template <class Impl>
void
AlphaFullCPU<Impl>::trap(Fault fault)
{
- // Keep in mind that a trap may be initiated by fetch if there's a TLB
+/* // 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->name());
+ this->recordEvent(csprintf("Fault %s", fault->name()));
-// kernelStats.fault(fault);
+ //kernelStats.fault(fault);
- if (fault == Arithmetic_Fault)
+ if (fault->isA<ArithmeticFault>())
panic("Arithmetic traps are unimplemented!");
- typename AlphaISA::InternalProcReg *ipr = getIpr();
-
// exception restart address - Get the commit PC
- if (fault != Interrupt_Fault || !inPalMode(PC))
- ipr[AlphaISA::IPR_EXC_ADDR] = PC;
+ if (!fault->isA<InterruptFault>() || !inPalMode(PC))
+ this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, PC);
- if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
- fault == Interrupt_Fault && !PC_PAL(regs.pc) */) {
+ if (fault->isA<PalFault>() || fault->isA<ArithmeticFault>())
+ // || fault == InterruptFault && !PC_PAL(regs.pc)
+ {
// traps... skip faulting instruction
- ipr[AlphaISA::IPR_EXC_ADDR] += 4;
+ AlphaISA::MiscReg ipr_exc_addr =
+ this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR);
+ this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR,
+ ipr_exc_addr + 4);
}
if (!inPalMode(PC))
swapPALShadow(true);
- this->regFile.setPC( ipr[AlphaISA::IPR_PAL_BASE] +
- AlphaISA::fault_addr[fault] );
- this->regFile.setNextPC(PC + sizeof(MachInst));
+ this->regFile.setPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_PAL_BASE) +
+ (dynamic_cast<AlphaFault *>(fault.get()))->vect());
+ this->regFile.setNextPC(PC + sizeof(MachInst));*/
}
template <class Impl>
diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh
index bb90bf21a..e7f7d3a57 100644
--- a/cpu/o3/alpha_dyn_inst.hh
+++ b/cpu/o3/alpha_dyn_inst.hh
@@ -48,21 +48,18 @@ class AlphaDynInst : public BaseDynInst<Impl>
/** Typedef for the CPU. */
typedef typename Impl::FullCPU FullCPU;
- /** Typedef to get the ISA. */
- typedef typename Impl::ISA ISA;
-
/** Binary machine instruction type. */
- typedef typename ISA::MachInst MachInst;
- /** Memory address type. */
- typedef typename ISA::Addr Addr;
+ typedef TheISA::MachInst MachInst;
/** Logical register index type. */
- typedef typename ISA::RegIndex RegIndex;
+ typedef TheISA::RegIndex RegIndex;
/** Integer register index type. */
- typedef typename ISA::IntReg IntReg;
+ typedef TheISA::IntReg IntReg;
+ /** Misc register index type. */
+ typedef TheISA::MiscReg MiscReg;
enum {
- MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
};
public:
@@ -71,7 +68,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
FullCPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
- AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst);
+ AlphaDynInst(StaticInstPtr &_staticInst);
/** Executes the instruction.*/
Fault execute()
@@ -80,15 +77,35 @@ class AlphaDynInst : public BaseDynInst<Impl>
}
public:
- uint64_t readUniq();
- void setUniq(uint64_t val);
+ MiscReg readMiscReg(int misc_reg)
+ {
+ // Dummy function for now.
+ // @todo: Fix this once reg file gets fixed.
+ return 0;
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ // Dummy function for now.
+ // @todo: Fix this once reg file gets fixed.
+ return 0;
+ }
- uint64_t readFpcr();
- void setFpcr(uint64_t val);
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ // Dummy function for now.
+ // @todo: Fix this once reg file gets fixed.
+ return NoFault;
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ // Dummy function for now.
+ // @todo: Fix this once reg file gets fixed.
+ return NoFault;
+ }
#if FULL_SYSTEM
- uint64_t readIpr(int idx, Fault &fault);
- Fault setIpr(int idx, uint64_t val);
Fault hwrei();
int readIntrFlag();
void setIntrFlag(int val);
@@ -130,22 +147,22 @@ class AlphaDynInst : public BaseDynInst<Impl>
// storage (which is pretty hard to imagine they would have reason
// to do).
- uint64_t readIntReg(const StaticInst<ISA> *si, int idx)
+ uint64_t readIntReg(const StaticInst *si, int idx)
{
return this->cpu->readIntReg(_srcRegIdx[idx]);
}
- float readFloatRegSingle(const StaticInst<ISA> *si, int idx)
+ float readFloatRegSingle(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegSingle(_srcRegIdx[idx]);
}
- double readFloatRegDouble(const StaticInst<ISA> *si, int idx)
+ double readFloatRegDouble(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegDouble(_srcRegIdx[idx]);
}
- uint64_t readFloatRegInt(const StaticInst<ISA> *si, int idx)
+ uint64_t readFloatRegInt(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegInt(_srcRegIdx[idx]);
}
@@ -153,25 +170,25 @@ class AlphaDynInst : public BaseDynInst<Impl>
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
- void setIntReg(const StaticInst<ISA> *si, int idx, uint64_t val)
+ void setIntReg(const StaticInst *si, int idx, uint64_t val)
{
this->cpu->setIntReg(_destRegIdx[idx], val);
this->instResult.integer = val;
}
- void setFloatRegSingle(const StaticInst<ISA> *si, int idx, float val)
+ void setFloatRegSingle(const StaticInst *si, int idx, float val)
{
this->cpu->setFloatRegSingle(_destRegIdx[idx], val);
this->instResult.fp = val;
}
- void setFloatRegDouble(const StaticInst<ISA> *si, int idx, double val)
+ void setFloatRegDouble(const StaticInst *si, int idx, double val)
{
this->cpu->setFloatRegDouble(_destRegIdx[idx], val);
this->instResult.dbl = val;
}
- void setFloatRegInt(const StaticInst<ISA> *si, int idx, uint64_t val)
+ void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
{
this->cpu->setFloatRegInt(_destRegIdx[idx], val);
this->instResult.integer = val;
diff --git a/cpu/o3/alpha_dyn_inst_impl.hh b/cpu/o3/alpha_dyn_inst_impl.hh
index d1ebb812d..96b7d3430 100644
--- a/cpu/o3/alpha_dyn_inst_impl.hh
+++ b/cpu/o3/alpha_dyn_inst_impl.hh
@@ -50,7 +50,7 @@ AlphaDynInst<Impl>::AlphaDynInst(MachInst inst, Addr PC, Addr Pred_PC,
}
template <class Impl>
-AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst)
+AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst)
: BaseDynInst<Impl>(_staticInst)
{
// Make sure to have the renamed register entries set to the same
@@ -67,50 +67,8 @@ AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst)
}
}
-template <class Impl>
-uint64_t
-AlphaDynInst<Impl>::readUniq()
-{
- return this->cpu->readUniq();
-}
-
-template <class Impl>
-void
-AlphaDynInst<Impl>::setUniq(uint64_t val)
-{
- this->cpu->setUniq(val);
-}
-
-template <class Impl>
-uint64_t
-AlphaDynInst<Impl>::readFpcr()
-{
- return this->cpu->readFpcr();
-}
-
-template <class Impl>
-void
-AlphaDynInst<Impl>::setFpcr(uint64_t val)
-{
- this->cpu->setFpcr(val);
-}
-
#if FULL_SYSTEM
template <class Impl>
-uint64_t
-AlphaDynInst<Impl>::readIpr(int idx, Fault &fault)
-{
- return this->cpu->readIpr(idx, fault);
-}
-
-template <class Impl>
-Fault
-AlphaDynInst<Impl>::setIpr(int idx, uint64_t val)
-{
- return this->cpu->setIpr(idx, val);
-}
-
-template <class Impl>
Fault
AlphaDynInst<Impl>::hwrei()
{
diff --git a/cpu/o3/alpha_impl.hh b/cpu/o3/alpha_impl.hh
index 6c1156041..5e39fcb37 100644
--- a/cpu/o3/alpha_impl.hh
+++ b/cpu/o3/alpha_impl.hh
@@ -51,11 +51,8 @@ class AlphaFullCPU;
*/
struct AlphaSimpleImpl
{
- /** The ISA to be used. */
- typedef AlphaISA ISA;
-
/** The type of MachInst. */
- typedef ISA::MachInst MachInst;
+ typedef TheISA::MachInst MachInst;
/** The CPU policy to be used (ie fetch, decode, etc.). */
typedef SimpleCPUPolicy<AlphaSimpleImpl> CPUPol;
diff --git a/cpu/o3/bpred_unit.hh b/cpu/o3/bpred_unit.hh
index 0a77b83dc..2725684f7 100644
--- a/cpu/o3/bpred_unit.hh
+++ b/cpu/o3/bpred_unit.hh
@@ -30,7 +30,7 @@
#define __BPRED_UNIT_HH__
// For Addr type.
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "cpu/inst_seq.hh"
diff --git a/cpu/o3/bpred_unit_impl.hh b/cpu/o3/bpred_unit_impl.hh
index 9cb2e0490..8d16a0cdf 100644
--- a/cpu/o3/bpred_unit_impl.hh
+++ b/cpu/o3/bpred_unit_impl.hh
@@ -98,6 +98,8 @@ TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC)
// Save off record of branch stuff so the RAS can be fixed
// up once it's done.
+ using TheISA::MachInst;
+
bool pred_taken = false;
Addr target;
diff --git a/cpu/o3/btb.cc b/cpu/o3/btb.cc
index 7671e61e2..2d39c3856 100644
--- a/cpu/o3/btb.cc
+++ b/cpu/o3/btb.cc
@@ -30,6 +30,8 @@
#include "base/trace.hh"
#include "cpu/o3/btb.hh"
+using namespace TheISA;
+
DefaultBTB::DefaultBTB(unsigned _numEntries,
unsigned _tagBits,
unsigned _instShiftAmt)
diff --git a/cpu/o3/btb.hh b/cpu/o3/btb.hh
index a4ddfecb4..77bdc32ea 100644
--- a/cpu/o3/btb.hh
+++ b/cpu/o3/btb.hh
@@ -30,7 +30,7 @@
#define __CPU_O3_CPU_BTB_HH__
// For Addr type.
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
class DefaultBTB
{
diff --git a/cpu/o3/comm.hh b/cpu/o3/comm.hh
index e4de1d304..c74c77ddf 100644
--- a/cpu/o3/comm.hh
+++ b/cpu/o3/comm.hh
@@ -31,7 +31,7 @@
#include <vector>
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
#include "sim/host.hh"
diff --git a/cpu/o3/commit.hh b/cpu/o3/commit.hh
index 6ddc8d6b9..580c1a316 100644
--- a/cpu/o3/commit.hh
+++ b/cpu/o3/commit.hh
@@ -52,7 +52,6 @@ class SimpleCommit
{
public:
// Typedefs from the Impl.
- typedef typename Impl::ISA ISA;
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
diff --git a/cpu/o3/commit_impl.hh b/cpu/o3/commit_impl.hh
index dc0986772..e289bc0c0 100644
--- a/cpu/o3/commit_impl.hh
+++ b/cpu/o3/commit_impl.hh
@@ -395,7 +395,7 @@ SimpleCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
// Check if the instruction caused a fault. If so, trap.
Fault inst_fault = head_inst->getFault();
- if (inst_fault != No_Fault && inst_fault != Fake_Mem_Fault) {
+ if (inst_fault != NoFault) {
if (!head_inst->isNop()) {
#if FULL_SYSTEM
cpu->trap(inst_fault);
diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc
index adc7b6bbc..62d68bb33 100644
--- a/cpu/o3/cpu.cc
+++ b/cpu/o3/cpu.cc
@@ -35,10 +35,11 @@
#endif
#include "sim/root.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/cpu.hh"
-#include "cpu/exec_context.hh"
using namespace std;
@@ -84,14 +85,14 @@ FullO3CPU<Impl>::FullO3CPU(Params &params)
regFile(params.numPhysIntRegs, params.numPhysFloatRegs),
- freeList(Impl::ISA::NumIntRegs, params.numPhysIntRegs,
- Impl::ISA::NumFloatRegs, params.numPhysFloatRegs),
+ freeList(TheISA::NumIntRegs, params.numPhysIntRegs,
+ TheISA::NumFloatRegs, params.numPhysFloatRegs),
- renameMap(Impl::ISA::NumIntRegs, params.numPhysIntRegs,
- Impl::ISA::NumFloatRegs, params.numPhysFloatRegs,
- Impl::ISA::NumMiscRegs,
- Impl::ISA::ZeroReg,
- Impl::ISA::ZeroReg + Impl::ISA::NumIntRegs),
+ renameMap(TheISA::NumIntRegs, params.numPhysIntRegs,
+ TheISA::NumFloatRegs, params.numPhysFloatRegs,
+ TheISA::NumMiscRegs,
+ TheISA::ZeroReg,
+ TheISA::ZeroReg + TheISA::NumIntRegs),
rob(params.numROBEntries, params.squashWidth),
@@ -103,7 +104,7 @@ FullO3CPU<Impl>::FullO3CPU(Params &params)
renameQueue(5, 5),
iewQueue(5, 5),
- xc(NULL),
+ cpuXC(NULL),
globalSeqNum(1),
@@ -134,32 +135,26 @@ FullO3CPU<Impl>::FullO3CPU(Params &params)
for (int i = 0; i < this->number_of_threads; ++i) {
#if FULL_SYSTEM
assert(i == 0);
- system->execContexts[i] =
- new ExecContext(this, i, system, itb, dtb, mem);
+ thread[i] = new CPUExecContext(this, 0, system, itb, dtb, mem);
+ system->execContexts[i] = thread[i]->getProxy();
- // initialize CPU, including PC
- TheISA::initCPU(&system->execContexts[i]->regs);
execContexts.push_back(system->execContexts[i]);
#else
if (i < params.workload.size()) {
DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
"process is %#x",
i, params.workload[i]->prog_entry, thread[i]);
- thread[i] = new ExecContext(this, i, params.workload[i], i);
+ thread[i] = new CPUExecContext(this, i, params.workload[i], i);
}
assert(params.workload[i]->getMemory() != NULL);
assert(mem != NULL);
- execContexts.push_back(thread[i]);
+ execContexts.push_back(thread[i]->getProxy());
#endif // !FULL_SYSTEM
}
// Note that this is a hack so that my code which still uses xc-> will
// still work. I should remove this eventually
-#if FULL_SYSTEM
- xc = system->execContexts[0];
-#else
- xc = thread[0];
-#endif
+ cpuXC = thread[0];
// The stages also need their CPU pointer setup. However this must be
// done at the upper level CPU because they have pointers to the upper
@@ -250,31 +245,32 @@ FullO3CPU<Impl>::init()
// that it can start properly.
#if FULL_SYSTEM
ExecContext *src_xc = system->execContexts[0];
+ TheISA::initCPU(src_xc, src_xc->readCpuId());
#else
- ExecContext *src_xc = thread[0];
+ ExecContext *src_xc = thread[0]->getProxy();
#endif
// First loop through the integer registers.
- for (int i = 0; i < Impl::ISA::NumIntRegs; ++i)
+ for (int i = 0; i < TheISA::NumIntRegs; ++i)
{
- regFile.intRegFile[i] = src_xc->regs.intRegFile[i];
+ regFile.intRegFile[i] = src_xc->readIntReg(i);
}
// Then loop through the floating point registers.
- for (int i = 0; i < Impl::ISA::NumFloatRegs; ++i)
+ for (int i = 0; i < TheISA::NumFloatRegs; ++i)
{
- regFile.floatRegFile[i].d = src_xc->regs.floatRegFile.d[i];
- regFile.floatRegFile[i].q = src_xc->regs.floatRegFile.q[i];
+ regFile.floatRegFile[i].d = src_xc->readFloatRegDouble(i);
+ regFile.floatRegFile[i].q = src_xc->readFloatRegInt(i);
}
-
+/*
// Then loop through the misc registers.
regFile.miscRegs.fpcr = src_xc->regs.miscRegs.fpcr;
regFile.miscRegs.uniq = src_xc->regs.miscRegs.uniq;
regFile.miscRegs.lock_flag = src_xc->regs.miscRegs.lock_flag;
regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr;
-
+*/
// Then finally set the PC and the next PC.
- regFile.pc = src_xc->regs.pc;
- regFile.npc = src_xc->regs.npc;
+ regFile.pc = src_xc->readPC();
+ regFile.npc = src_xc->readNextPC();
}
}
diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh
index 75dca5056..6577e46e4 100644
--- a/cpu/o3/cpu.hh
+++ b/cpu/o3/cpu.hh
@@ -44,16 +44,12 @@
#include "base/timebuf.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/cpu_policy.hh"
-#include "cpu/exec_context.hh"
#include "sim/process.hh"
-#if FULL_SYSTEM
-#include "arch/alpha/ev5.hh"
-using namespace EV5;
-#endif
-
+class ExecContext;
class FunctionalMemory;
class Process;
@@ -78,7 +74,6 @@ class FullO3CPU : public BaseFullCPU
{
public:
//Put typedefs from the Impl here.
- typedef typename Impl::ISA ISA;
typedef typename Impl::CPUPol CPUPolicy;
typedef typename Impl::Params Params;
typedef typename Impl::DynInstPtr DynInstPtr;
@@ -153,11 +148,11 @@ class FullO3CPU : public BaseFullCPU
/** Get instruction asid. */
int getInstAsid()
- { return ITB_ASN_ASN(regFile.getIpr()[ISA::IPR_ITB_ASN]); }
+ { return regFile.miscRegs.getInstAsid(); }
/** Get data asid. */
int getDataAsid()
- { return DTB_ASN_ASN(regFile.getIpr()[ISA::IPR_DTB_ASN]); }
+ { return regFile.miscRegs.getDataAsid(); }
#else
bool validInstAddr(Addr addr)
{ return thread[0]->validInstAddr(addr); }
@@ -165,8 +160,8 @@ class FullO3CPU : public BaseFullCPU
bool validDataAddr(Addr addr)
{ return thread[0]->validDataAddr(addr); }
- int getInstAsid() { return thread[0]->asid; }
- int getDataAsid() { return thread[0]->asid; }
+ int getInstAsid() { return thread[0]->getInstAsid(); }
+ int getDataAsid() { return thread[0]->getDataAsid(); }
#endif
@@ -321,16 +316,17 @@ class FullO3CPU : public BaseFullCPU
public:
/** The temporary exec context to support older accessors. */
- ExecContext *xc;
+ CPUExecContext *cpuXC;
/** Temporary function to get pointer to exec context. */
ExecContext *xcBase()
{
-#if FULL_SYSTEM
- return system->execContexts[0];
-#else
+ return thread[0]->getProxy();
+ }
+
+ CPUExecContext *cpuXCBase()
+ {
return thread[0];
-#endif
}
InstSeqNum globalSeqNum;
@@ -345,9 +341,8 @@ class FullO3CPU : public BaseFullCPU
AlphaDTB *dtb;
// SWContext *swCtx;
-#else
- std::vector<ExecContext *> thread;
#endif
+ std::vector<CPUExecContext *> thread;
FunctionalMemory *mem;
diff --git a/cpu/o3/decode.hh b/cpu/o3/decode.hh
index 42313d83a..5b9a0f822 100644
--- a/cpu/o3/decode.hh
+++ b/cpu/o3/decode.hh
@@ -39,7 +39,6 @@ class SimpleDecode
{
private:
// Typedefs from the Impl.
- typedef typename Impl::ISA ISA;
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
@@ -50,9 +49,6 @@ class SimpleDecode
typedef typename CPUPol::DecodeStruct DecodeStruct;
typedef typename CPUPol::TimeStruct TimeStruct;
- // Typedefs from the ISA.
- typedef typename ISA::Addr Addr;
-
public:
// The only time decode will become blocked is if dispatch becomes
// blocked, which means IQ or ROB is probably full.
diff --git a/cpu/o3/fetch.hh b/cpu/o3/fetch.hh
index 24e445f0b..cc64800d9 100644
--- a/cpu/o3/fetch.hh
+++ b/cpu/o3/fetch.hh
@@ -49,7 +49,6 @@ class SimpleFetch
{
public:
/** Typedefs from Impl. */
- typedef typename Impl::ISA ISA;
typedef typename Impl::CPUPol CPUPol;
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
@@ -61,7 +60,7 @@ class SimpleFetch
typedef typename CPUPol::TimeStruct TimeStruct;
/** Typedefs from ISA. */
- typedef typename ISA::MachInst MachInst;
+ typedef TheISA::MachInst MachInst;
public:
enum Status {
@@ -141,7 +140,7 @@ class SimpleFetch
// We fold in the PISA 64- to 32-bit conversion here as well.
Addr icacheBlockAlignPC(Addr addr)
{
- addr = ISA::realPCToFetchPC(addr);
+ addr = TheISA::realPCToFetchPC(addr);
return (addr & ~(cacheBlkMask));
}
diff --git a/cpu/o3/fetch_impl.hh b/cpu/o3/fetch_impl.hh
index c943fd36a..8029fc732 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"
@@ -236,7 +236,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
unsigned flags = 0;
#endif // FULL_SYSTEM
- Fault fault = No_Fault;
+ Fault fault = NoFault;
// Align the fetch PC so it's at the start of a cache block.
fetch_PC = icacheBlockAlignPC(fetch_PC);
@@ -258,7 +258,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
// If translation was successful, attempt to read the first
// instruction.
- if (fault == No_Fault) {
+ if (fault == NoFault) {
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
fault = cpu->mem->read(memReq, cacheData);
// This read may change when the mem interface changes.
@@ -268,7 +268,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC)
// Now do the timing access to see whether or not the instruction
// exists within the cache.
- if (icacheInterface && fault == No_Fault) {
+ if (icacheInterface && fault == NoFault) {
DPRINTF(Fetch, "Fetch: Doing timing memory access.\n");
memReq->completionEvent = NULL;
@@ -468,7 +468,7 @@ SimpleFetch<Impl>::fetch()
Addr fetch_PC = cpu->readPC();
// Fault code for memory access.
- Fault fault = No_Fault;
+ Fault fault = NoFault;
// If returning from the delay of a cache miss, then update the status
// to running, otherwise do the cache access. Possibly move this up
@@ -506,7 +506,7 @@ SimpleFetch<Impl>::fetch()
unsigned offset = fetch_PC & cacheBlkMask;
unsigned fetched;
- if (fault == No_Fault) {
+ if (fault == NoFault) {
// If the read of the first instruction was successful, then grab the
// instructions from the rest of the cache line and put them into the
// queue heading to decode.
@@ -582,7 +582,7 @@ SimpleFetch<Impl>::fetch()
// Or might want to leave setting the PC to the main CPU, with fetch
// only changing the nextPC (will require correct determination of
// next PC).
- if (fault == No_Fault) {
+ if (fault == NoFault) {
DPRINTF(Fetch, "Fetch: Setting PC to %08p.\n", next_PC);
cpu->setPC(next_PC);
cpu->setNextPC(next_PC + instSize);
diff --git a/cpu/o3/free_list.hh b/cpu/o3/free_list.hh
index 733d142fc..0b85dba1e 100644
--- a/cpu/o3/free_list.hh
+++ b/cpu/o3/free_list.hh
@@ -32,7 +32,7 @@
#include <iostream>
#include <queue>
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "base/trace.hh"
#include "base/traceflags.hh"
#include "cpu/o3/comm.hh"
diff --git a/cpu/o3/iew.hh b/cpu/o3/iew.hh
index af23c6f45..1e370d4e6 100644
--- a/cpu/o3/iew.hh
+++ b/cpu/o3/iew.hh
@@ -45,7 +45,6 @@ class SimpleIEW
{
private:
//Typedefs from Impl
- typedef typename Impl::ISA ISA;
typedef typename Impl::CPUPol CPUPol;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::FullCPU FullCPU;
diff --git a/cpu/o3/iew_impl.hh b/cpu/o3/iew_impl.hh
index b8a2b4dc9..85217dd10 100644
--- a/cpu/o3/iew_impl.hh
+++ b/cpu/o3/iew_impl.hh
@@ -256,7 +256,7 @@ SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
toCommit->branchMispredict = true;
// Prediction was incorrect, so send back inverse.
toCommit->branchTaken = inst->readNextPC() !=
- (inst->readPC() + sizeof(MachInst));
+ (inst->readPC() + sizeof(TheISA::MachInst));
}
template<class Impl>
diff --git a/cpu/o3/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/ras.hh b/cpu/o3/ras.hh
index bbc4162a6..46d98181e 100644
--- a/cpu/o3/ras.hh
+++ b/cpu/o3/ras.hh
@@ -30,7 +30,7 @@
#define __CPU_O3_CPU_RAS_HH__
// For Addr type.
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
class ReturnAddrStack
{
diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh
index 4d47b8f9c..1e6e10f29 100644
--- a/cpu/o3/regfile.hh
+++ b/cpu/o3/regfile.hh
@@ -31,16 +31,15 @@
// @todo: Destructor
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
+#include "arch/faults.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/o3/comm.hh"
#if FULL_SYSTEM
-#include "arch/alpha/ev5.hh"
#include "kern/kernel_stats.hh"
-using namespace EV5;
#endif
// This really only depends on the ISA, and not the Impl. It might be nicer
@@ -51,6 +50,12 @@ using namespace EV5;
template <class Impl>
class PhysRegFile
{
+ protected:
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::MiscRegFile MiscRegFile;
+ typedef TheISA::MiscReg MiscReg;
+
//Note that most of the definitions of the IntReg, FloatReg, etc. exist
//within the Impl/ISA class and not within this PhysRegFile class.
@@ -61,7 +66,6 @@ class PhysRegFile
//Will make these registers public for now, but they probably should
//be private eventually with some accessor functions.
public:
- typedef typename Impl::ISA ISA;
typedef typename Impl::FullCPU FullCPU;
PhysRegFile(unsigned _numPhysicalIntRegs,
@@ -190,30 +194,21 @@ class PhysRegFile
//Consider leaving this stuff and below in some implementation specific
//file as opposed to the general register file. Or have a derived class.
- uint64_t readUniq()
- {
- return miscRegs.uniq;
- }
-
- void setUniq(uint64_t val)
- {
- miscRegs.uniq = val;
- }
-
- uint64_t readFpcr()
+ MiscReg readMiscReg(int misc_reg)
{
- return miscRegs.fpcr;
+ // Dummy function for now.
+ // @todo: Fix this once proxy XC is used.
+ return 0;
}
- void setFpcr(uint64_t val)
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
{
- miscRegs.fpcr = val;
+ // Dummy function for now.
+ // @todo: Fix this once proxy XC is used.
+ return NoFault;
}
#if FULL_SYSTEM
- 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; }
#endif
@@ -239,8 +234,7 @@ class PhysRegFile
#if FULL_SYSTEM
private:
// This is ISA specifc stuff; remove it eventually once ISAImpl is used
- IntReg palregs[NumIntRegs]; // PAL shadow registers
- InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
+// IntReg palregs[NumIntRegs]; // PAL shadow registers
int intrflag; // interrupt flag
bool pal_shadow; // using pal_shadow registers
#endif
@@ -268,368 +262,4 @@ PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
memset(floatRegFile, 0, sizeof(*floatRegFile));
}
-#if FULL_SYSTEM
-
-//Problem: This code doesn't make sense at the RegFile level because it
-//needs things such as the itb and dtb. Either put it at the CPU level or
-//the DynInst level.
-template <class Impl>
-uint64_t
-PhysRegFile<Impl>::readIpr(int idx, Fault &fault)
-{
- uint64_t retval = 0; // return value, default 0
-
- switch (idx) {
- case ISA::IPR_PALtemp0:
- case ISA::IPR_PALtemp1:
- case ISA::IPR_PALtemp2:
- case ISA::IPR_PALtemp3:
- case ISA::IPR_PALtemp4:
- case ISA::IPR_PALtemp5:
- case ISA::IPR_PALtemp6:
- case ISA::IPR_PALtemp7:
- case ISA::IPR_PALtemp8:
- case ISA::IPR_PALtemp9:
- case ISA::IPR_PALtemp10:
- case ISA::IPR_PALtemp11:
- case ISA::IPR_PALtemp12:
- case ISA::IPR_PALtemp13:
- case ISA::IPR_PALtemp14:
- case ISA::IPR_PALtemp15:
- case ISA::IPR_PALtemp16:
- case ISA::IPR_PALtemp17:
- case ISA::IPR_PALtemp18:
- case ISA::IPR_PALtemp19:
- case ISA::IPR_PALtemp20:
- case ISA::IPR_PALtemp21:
- case ISA::IPR_PALtemp22:
- case ISA::IPR_PALtemp23:
- case ISA::IPR_PAL_BASE:
-
- case ISA::IPR_IVPTBR:
- case ISA::IPR_DC_MODE:
- case ISA::IPR_MAF_MODE:
- case ISA::IPR_ISR:
- case ISA::IPR_EXC_ADDR:
- case ISA::IPR_IC_PERR_STAT:
- case ISA::IPR_DC_PERR_STAT:
- case ISA::IPR_MCSR:
- case ISA::IPR_ASTRR:
- case ISA::IPR_ASTER:
- case ISA::IPR_SIRR:
- case ISA::IPR_ICSR:
- case ISA::IPR_ICM:
- case ISA::IPR_DTB_CM:
- case ISA::IPR_IPLR:
- case ISA::IPR_INTID:
- case ISA::IPR_PMCTR:
- // no side-effect
- retval = ipr[idx];
- break;
-
- case ISA::IPR_CC:
- retval |= ipr[idx] & ULL(0xffffffff00000000);
- retval |= curTick & ULL(0x00000000ffffffff);
- break;
-
- case ISA::IPR_VA:
- retval = ipr[idx];
- break;
-
- case ISA::IPR_VA_FORM:
- case ISA::IPR_MM_STAT:
- case ISA::IPR_IFAULT_VA_FORM:
- case ISA::IPR_EXC_MASK:
- case ISA::IPR_EXC_SUM:
- retval = ipr[idx];
- break;
-
- case ISA::IPR_DTB_PTE:
- {
- typename ISA::PTE &pte = cpu->dtb->index(1);
-
- retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
- retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
- retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
- retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
- retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
- retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
- retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
- }
- break;
-
- // write only registers
- case ISA::IPR_HWINT_CLR:
- case ISA::IPR_SL_XMIT:
- case ISA::IPR_DC_FLUSH:
- case ISA::IPR_IC_FLUSH:
- case ISA::IPR_ALT_MODE:
- case ISA::IPR_DTB_IA:
- case ISA::IPR_DTB_IAP:
- case ISA::IPR_ITB_IA:
- case ISA::IPR_ITB_IAP:
- fault = Unimplemented_Opcode_Fault;
- break;
-
- default:
- // invalid IPR
- fault = Unimplemented_Opcode_Fault;
- break;
- }
-
- return retval;
-}
-
-extern int break_ipl;
-
-template <class Impl>
-Fault
-PhysRegFile<Impl>::setIpr(int idx, uint64_t val)
-{
- uint64_t old;
-
- switch (idx) {
- case ISA::IPR_PALtemp0:
- case ISA::IPR_PALtemp1:
- case ISA::IPR_PALtemp2:
- case ISA::IPR_PALtemp3:
- case ISA::IPR_PALtemp4:
- case ISA::IPR_PALtemp5:
- case ISA::IPR_PALtemp6:
- case ISA::IPR_PALtemp7:
- case ISA::IPR_PALtemp8:
- case ISA::IPR_PALtemp9:
- case ISA::IPR_PALtemp10:
- case ISA::IPR_PALtemp11:
- case ISA::IPR_PALtemp12:
- case ISA::IPR_PALtemp13:
- case ISA::IPR_PALtemp14:
- case ISA::IPR_PALtemp15:
- case ISA::IPR_PALtemp16:
- case ISA::IPR_PALtemp17:
- case ISA::IPR_PALtemp18:
- case ISA::IPR_PALtemp19:
- case ISA::IPR_PALtemp20:
- case ISA::IPR_PALtemp21:
- case ISA::IPR_PALtemp22:
- case ISA::IPR_PAL_BASE:
- case ISA::IPR_IC_PERR_STAT:
- case ISA::IPR_DC_PERR_STAT:
- case ISA::IPR_PMCTR:
- // write entire quad w/ no side-effect
- ipr[idx] = val;
- break;
-
- case ISA::IPR_CC_CTL:
- // This IPR resets the cycle counter. We assume this only
- // happens once... let's verify that.
- assert(ipr[idx] == 0);
- ipr[idx] = 1;
- break;
-
- case ISA::IPR_CC:
- // This IPR only writes the upper 64 bits. It's ok to write
- // all 64 here since we mask out the lower 32 in rpcc (see
- // isa_desc).
- ipr[idx] = val;
- break;
-
- case ISA::IPR_PALtemp23:
- // write entire quad w/ no side-effect
- old = ipr[idx];
- ipr[idx] = val;
- break;
-
- case ISA::IPR_DTB_PTE:
- // write entire quad w/ no side-effect, tag is forthcoming
- ipr[idx] = val;
- break;
-
- case ISA::IPR_EXC_ADDR:
- // second least significant bit in PC is always zero
- ipr[idx] = val & ~2;
- break;
-
- case ISA::IPR_ASTRR:
- case ISA::IPR_ASTER:
- // only write least significant four bits - privilege mask
- ipr[idx] = val & 0xf;
- break;
-
- case ISA::IPR_IPLR:
- // only write least significant five bits - interrupt level
- ipr[idx] = val & 0x1f;
- break;
-
- case ISA::IPR_DTB_CM:
-
- case ISA::IPR_ICM:
- // only write two mode bits - processor mode
- ipr[idx] = val & 0x18;
- break;
-
- case ISA::IPR_ALT_MODE:
- // only write two mode bits - processor mode
- ipr[idx] = val & 0x18;
- break;
-
- case ISA::IPR_MCSR:
- // more here after optimization...
- ipr[idx] = val;
- break;
-
- case ISA::IPR_SIRR:
- // only write software interrupt mask
- ipr[idx] = val & 0x7fff0;
- break;
-
- case ISA::IPR_ICSR:
- ipr[idx] = val & ULL(0xffffff0300);
- break;
-
- case ISA::IPR_IVPTBR:
- case ISA::IPR_MVPTBR:
- ipr[idx] = val & ULL(0xffffffffc0000000);
- break;
-
- case ISA::IPR_DC_TEST_CTL:
- ipr[idx] = val & 0x1ffb;
- break;
-
- case ISA::IPR_DC_MODE:
- case ISA::IPR_MAF_MODE:
- ipr[idx] = val & 0x3f;
- break;
-
- case ISA::IPR_ITB_ASN:
- ipr[idx] = val & 0x7f0;
- break;
-
- case ISA::IPR_DTB_ASN:
- ipr[idx] = val & ULL(0xfe00000000000000);
- break;
-
- case ISA::IPR_EXC_SUM:
- case ISA::IPR_EXC_MASK:
- // any write to this register clears it
- ipr[idx] = 0;
- break;
-
- case ISA::IPR_INTID:
- case ISA::IPR_SL_RCV:
- case ISA::IPR_MM_STAT:
- case ISA::IPR_ITB_PTE_TEMP:
- case ISA::IPR_DTB_PTE_TEMP:
- // read-only registers
- return Unimplemented_Opcode_Fault;
-
- case ISA::IPR_HWINT_CLR:
- case ISA::IPR_SL_XMIT:
- case ISA::IPR_DC_FLUSH:
- case ISA::IPR_IC_FLUSH:
- // the following are write only
- ipr[idx] = val;
- break;
-
- case ISA::IPR_DTB_IA:
- // really a control write
- ipr[idx] = 0;
-
- cpu->dtb->flushAll();
- break;
-
- case ISA::IPR_DTB_IAP:
- // really a control write
- ipr[idx] = 0;
-
- cpu->dtb->flushProcesses();
- break;
-
- case ISA::IPR_DTB_IS:
- // really a control write
- ipr[idx] = val;
-
- cpu->dtb->flushAddr(val, DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN]));
- break;
-
- case ISA::IPR_DTB_TAG: {
- struct ISA::PTE pte;
-
- // FIXME: granularity hints NYI...
- if (DTB_PTE_GH(ipr[ISA::IPR_DTB_PTE]) != 0)
- panic("PTE GH field != 0");
-
- // write entire quad
- ipr[idx] = val;
-
- // construct PTE for new entry
- pte.ppn = DTB_PTE_PPN(ipr[ISA::IPR_DTB_PTE]);
- pte.xre = DTB_PTE_XRE(ipr[ISA::IPR_DTB_PTE]);
- pte.xwe = DTB_PTE_XWE(ipr[ISA::IPR_DTB_PTE]);
- pte.fonr = DTB_PTE_FONR(ipr[ISA::IPR_DTB_PTE]);
- pte.fonw = DTB_PTE_FONW(ipr[ISA::IPR_DTB_PTE]);
- pte.asma = DTB_PTE_ASMA(ipr[ISA::IPR_DTB_PTE]);
- pte.asn = DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN]);
-
- // insert new TAG/PTE value into data TLB
- cpu->dtb->insert(val, pte);
- }
- break;
-
- case ISA::IPR_ITB_PTE: {
- struct ISA::PTE pte;
-
- // FIXME: granularity hints NYI...
- if (ITB_PTE_GH(val) != 0)
- panic("PTE GH field != 0");
-
- // write entire quad
- ipr[idx] = val;
-
- // construct PTE for new entry
- pte.ppn = ITB_PTE_PPN(val);
- pte.xre = ITB_PTE_XRE(val);
- pte.xwe = 0;
- pte.fonr = ITB_PTE_FONR(val);
- pte.fonw = ITB_PTE_FONW(val);
- pte.asma = ITB_PTE_ASMA(val);
- pte.asn = ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN]);
-
- // insert new TAG/PTE value into data TLB
- cpu->itb->insert(ipr[ISA::IPR_ITB_TAG], pte);
- }
- break;
-
- case ISA::IPR_ITB_IA:
- // really a control write
- ipr[idx] = 0;
-
- cpu->itb->flushAll();
- break;
-
- case ISA::IPR_ITB_IAP:
- // really a control write
- ipr[idx] = 0;
-
- cpu->itb->flushProcesses();
- break;
-
- case ISA::IPR_ITB_IS:
- // really a control write
- ipr[idx] = val;
-
- cpu->itb->flushAddr(val, ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN]));
- break;
-
- default:
- // invalid IPR
- return Unimplemented_Opcode_Fault;
- }
-
- // no error...
- return No_Fault;
-}
-
-#endif // #if FULL_SYSTEM
-
#endif // __CPU_O3_CPU_REGFILE_HH__
diff --git a/cpu/o3/rename.hh b/cpu/o3/rename.hh
index a17ec7311..07b442964 100644
--- a/cpu/o3/rename.hh
+++ b/cpu/o3/rename.hh
@@ -46,7 +46,6 @@ class SimpleRename
{
public:
// Typedefs from the Impl.
- typedef typename Impl::ISA ISA;
typedef typename Impl::CPUPol CPUPol;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::FullCPU FullCPU;
@@ -62,7 +61,7 @@ class SimpleRename
typedef typename CPUPol::RenameMap RenameMap;
// Typedefs from the ISA.
- typedef typename ISA::Addr Addr;
+ typedef TheISA::RegIndex RegIndex;
public:
// Rename will block if ROB becomes full or issue queue becomes full,
diff --git a/cpu/o3/rename_map.hh b/cpu/o3/rename_map.hh
index c44c7a1ea..57be4a64a 100644
--- a/cpu/o3/rename_map.hh
+++ b/cpu/o3/rename_map.hh
@@ -38,9 +38,13 @@
#include <vector>
#include "cpu/o3/free_list.hh"
+//For RegIndex
+#include "arch/isa_traits.hh"
class SimpleRenameMap
{
+ protected:
+ typedef TheISA::RegIndex RegIndex;
public:
/**
* Pair of a logical register and a physical register. Tells the
diff --git a/cpu/o3/rob.hh b/cpu/o3/rob.hh
index 29ec48007..1185564ad 100644
--- a/cpu/o3/rob.hh
+++ b/cpu/o3/rob.hh
@@ -47,6 +47,8 @@
template <class Impl>
class ROB
{
+ protected:
+ typedef TheISA::RegIndex RegIndex;
public:
//Typedefs from the Impl.
typedef typename Impl::FullCPU FullCPU;
diff --git a/cpu/o3/store_set.hh b/cpu/o3/store_set.hh
index bcd590384..5a885d838 100644
--- a/cpu/o3/store_set.hh
+++ b/cpu/o3/store_set.hh
@@ -31,7 +31,7 @@
#include <vector>
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
class StoreSet
diff --git a/cpu/o3/tournament_pred.hh b/cpu/o3/tournament_pred.hh
index 58ea1a7d9..cb93c2f67 100644
--- a/cpu/o3/tournament_pred.hh
+++ b/cpu/o3/tournament_pred.hh
@@ -30,7 +30,7 @@
#define __CPU_O3_CPU_TOURNAMENT_PRED_HH__
// For Addr type.
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "cpu/o3/sat_counter.hh"
class TournamentBP
diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh
index 5af77862a..f5d84d656 100644
--- a/cpu/ozone/cpu.hh
+++ b/cpu/ozone/cpu.hh
@@ -77,7 +77,6 @@ class OoOCPU : public BaseCPU
private:
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::ISA ISA;
public:
// main simulation loop (one cycle)
@@ -320,7 +319,7 @@ class OoOCPU : public BaseCPU
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return No_Fault;
+ return NoFault;
}
Fault translateInstReq(MemReqPtr &req)
{
@@ -378,12 +377,12 @@ class OoOCPU : public BaseCPU
private:
InstSeqNum globalSeqNum;
- DynInstPtr renameTable[ISA::TotalNumRegs];
- DynInstPtr commitTable[ISA::TotalNumRegs];
+ DynInstPtr renameTable[TheISA::TotalNumRegs];
+ DynInstPtr commitTable[TheISA::TotalNumRegs];
// Might need a table of the shadow registers as well.
#if FULL_SYSTEM
- DynInstPtr palShadowTable[ISA::NumIntRegs];
+ DynInstPtr palShadowTable[TheISA::NumIntRegs];
#endif
public:
@@ -402,47 +401,47 @@ class OoOCPU : public BaseCPU
// rename table of DynInsts. Also these likely shouldn't be called very
// often, other than when adding things into the xc during say a syscall.
- uint64_t readIntReg(StaticInst<TheISA> *si, int idx)
+ uint64_t readIntReg(StaticInst *si, int idx)
{
return xc->readIntReg(si->srcRegIdx(idx));
}
- float readFloatRegSingle(StaticInst<TheISA> *si, int idx)
+ float readFloatRegSingle(StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegSingle(reg_idx);
}
- double readFloatRegDouble(StaticInst<TheISA> *si, int idx)
+ double readFloatRegDouble(StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegDouble(reg_idx);
}
- uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx)
+ uint64_t readFloatRegInt(StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegInt(reg_idx);
}
- void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val)
+ void setIntReg(StaticInst *si, int idx, uint64_t val)
{
xc->setIntReg(si->destRegIdx(idx), val);
}
- void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val)
+ void setFloatRegSingle(StaticInst *si, int idx, float val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegSingle(reg_idx, val);
}
- void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val)
+ void setFloatRegDouble(StaticInst *si, int idx, double val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegDouble(reg_idx, val);
}
- void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val)
+ void setFloatRegInt(StaticInst *si, int idx, uint64_t val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegInt(reg_idx, val);
@@ -479,7 +478,7 @@ class OoOCPU : public BaseCPU
// We fold in the PISA 64- to 32-bit conversion here as well.
Addr icacheBlockAlignPC(Addr addr)
{
- addr = ISA::realPCToFetchPC(addr);
+ addr = TheISA::realPCToFetchPC(addr);
return (addr & ~(cacheBlkMask));
}
@@ -518,7 +517,7 @@ class OoOCPU : public BaseCPU
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 trap(Fault fault) { fault->invoke(xc); }
bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
void syscall() { xc->syscall(); }
@@ -545,18 +544,18 @@ OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst)
Fault fault = translateDataReadReq(readReq);
// do functional access
- if (fault == No_Fault)
+ if (fault == NoFault)
fault = xc->mem->read(readReq, data);
#if 0
if (traceData) {
traceData->setAddr(addr);
- if (fault == No_Fault)
+ if (fault == NoFault)
traceData->setData(data);
}
#endif
// if we have a cache, do cache access too
- if (fault == No_Fault && dcacheInterface) {
+ if (fault == NoFault && dcacheInterface) {
readReq->cmd = Read;
readReq->completionEvent = NULL;
readReq->time = curTick;
@@ -598,10 +597,10 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
Fault fault = translateDataWriteReq(writeReq);
// do functional access
- if (fault == No_Fault)
+ if (fault == NoFault)
fault = xc->write(writeReq, data);
- if (fault == No_Fault && dcacheInterface) {
+ if (fault == NoFault && dcacheInterface) {
writeReq->cmd = Write;
memcpy(writeReq->data,(uint8_t *)&data,writeReq->size);
writeReq->completionEvent = NULL;
@@ -614,7 +613,7 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
}
}
- if (res && (fault == No_Fault))
+ if (res && (fault == NoFault))
*res = writeReq->result;
if (!dcacheInterface && (writeReq->flags & UNCACHEABLE))
diff --git a/cpu/ozone/cpu_impl.hh b/cpu/ozone/cpu_impl.hh
index 009a81b98..e7ed3cfe0 100644
--- a/cpu/ozone/cpu_impl.hh
+++ b/cpu/ozone/cpu_impl.hh
@@ -29,7 +29,7 @@
#ifndef __CPU_OOO_CPU_OOO_IMPL_HH__
#define __CPU_OOO_CPU_OOO_IMPL_HH__
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
template <class Impl>
class OoOCPU;
diff --git a/cpu/ozone/ea_list.cc b/cpu/ozone/ea_list.cc
index 80cf80fb8..6114a0ca1 100644
--- a/cpu/ozone/ea_list.cc
+++ b/cpu/ozone/ea_list.cc
@@ -26,7 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
#include "cpu/ooo_cpu/ea_list.hh"
diff --git a/cpu/ozone/ea_list.hh b/cpu/ozone/ea_list.hh
index def7e67d5..c0eee4bb8 100644
--- a/cpu/ozone/ea_list.hh
+++ b/cpu/ozone/ea_list.hh
@@ -32,7 +32,7 @@
#include <list>
#include <utility>
-#include "arch/alpha/isa_traits.hh"
+#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
/**
diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc
index 83fbc3e2d..050bf1a88 100644
--- a/cpu/pc_event.cc
+++ b/cpu/pc_event.cc
@@ -38,6 +38,7 @@
#include "cpu/pc_event.hh"
#include "sim/debug.hh"
#include "sim/root.hh"
+#include "sim/system.hh"
using namespace std;
@@ -79,7 +80,7 @@ PCEventQueue::schedule(PCEvent *event)
bool
PCEventQueue::doService(ExecContext *xc)
{
- Addr pc = xc->regs.pc & ~0x3;
+ Addr pc = xc->readPC() & ~0x3;
int serviced = 0;
range_t range = equal_range(pc);
for (iterator i = range.first; i != range.second; ++i) {
@@ -87,7 +88,7 @@ PCEventQueue::doService(ExecContext *xc)
// another event. This for example, prevents two invocations
// of the SkipFuncEvent. Maybe we should have separate PC
// event queues for each processor?
- if (pc != (xc->regs.pc & ~0x3))
+ if (pc != (xc->readPC() & ~0x3))
continue;
DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
@@ -126,7 +127,7 @@ BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
void
BreakPCEvent::process(ExecContext *xc)
{
- StringWrap name(xc->cpu->name() + ".break_event");
+ StringWrap name(xc->getCpuPtr()->name() + ".break_event");
DPRINTFN("break event %s triggered\n", descr());
debug_break();
if (remove)
diff --git a/cpu/profile.cc b/cpu/profile.cc
index 1a38792a0..fe3458b61 100644
--- a/cpu/profile.cc
+++ b/cpu/profile.cc
@@ -32,6 +32,7 @@
#include "base/callback.hh"
#include "base/statistics.hh"
#include "base/trace.hh"
+#include "base/loader/symtab.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "cpu/profile.hh"
diff --git a/cpu/profile.hh b/cpu/profile.hh
index 58cd7e79f..d55c9eec9 100644
--- a/cpu/profile.hh
+++ b/cpu/profile.hh
@@ -33,7 +33,9 @@
#include "cpu/static_inst.hh"
#include "sim/host.hh"
-#include "targetarch/stacktrace.hh"
+#include "arch/stacktrace.hh"
+
+class ExecContext;
class ProfileNode
{
@@ -68,7 +70,7 @@ class FunctionProfile
FunctionProfile(const SymbolTable *symtab);
~FunctionProfile();
- ProfileNode *consume(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ ProfileNode *consume(ExecContext *xc, StaticInstPtr inst);
ProfileNode *consume(const std::vector<Addr> &stack);
void clear();
void dump(ExecContext *xc, std::ostream &out) const;
@@ -76,7 +78,7 @@ class FunctionProfile
};
inline ProfileNode *
-FunctionProfile::consume(ExecContext *xc, StaticInstPtr<TheISA> inst)
+FunctionProfile::consume(ExecContext *xc, StaticInstPtr inst)
{
if (!trace.trace(xc, inst))
return NULL;
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
index d8d4c3644..fc70df662 100644
--- a/cpu/simple/cpu.cc
+++ b/cpu/simple/cpu.cc
@@ -44,6 +44,7 @@
#include "base/stats/events.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/profile.hh"
@@ -52,6 +53,7 @@
#include "cpu/smt.hh"
#include "cpu/static_inst.hh"
#include "kern/kernel_stats.hh"
+#include "sim/byteswap.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
@@ -64,14 +66,16 @@
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/system.hh"
-#include "targetarch/alpha_memory.hh"
-#include "targetarch/stacktrace.hh"
-#include "targetarch/vtophys.hh"
+#include "arch/tlb.hh"
+#include "arch/stacktrace.hh"
+#include "arch/vtophys.hh"
#else // !FULL_SYSTEM
#include "mem/memory.hh"
#endif // FULL_SYSTEM
using namespace std;
+//The SimpleCPU does alpha only
+using namespace AlphaISA;
SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
@@ -79,6 +83,21 @@ SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
{
}
+
+void
+SimpleCPU::init()
+{
+ BaseCPU::init();
+#if FULL_SYSTEM
+ for (int i = 0; i < execContexts.size(); ++i) {
+ ExecContext *xc = execContexts[i];
+
+ // initialize CPU, including PC
+ TheISA::initCPU(xc, xc->readCpuId());
+ }
+#endif
+}
+
void
SimpleCPU::TickEvent::process()
{
@@ -129,7 +148,7 @@ SimpleCPU::CpuPort::recvRetry()
SimpleCPU::SimpleCPU(Params *p)
: BaseCPU(p), icachePort(this),
- dcachePort(this), tickEvent(this, p->width), xc(NULL)
+ dcachePort(this), tickEvent(this, p->width), cpuXC(NULL)
{
_status = Idle;
@@ -143,15 +162,14 @@ SimpleCPU::SimpleCPU(Params *p)
(p->mem->getPort("ICACHE"))->setPeer(&icachePort);
#if FULL_SYSTEM
- xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
-
- // initialize CPU, including PC
- TheISA::initCPU(&xc->regs);
+ cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
#else
- xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0,
+ cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0,
&dcachePort);
#endif // !FULL_SYSTEM
+ xcProxy = cpuXC->getProxy();
+
#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
ifetch_req = new CpuRequest;
ifetch_req->asid = 0;
@@ -183,7 +201,7 @@ SimpleCPU::SimpleCPU(Params *p)
lastIcacheStall = 0;
lastDcacheStall = 0;
- execContexts.push_back(xc);
+ execContexts.push_back(xcProxy);
}
SimpleCPU::~SimpleCPU()
@@ -232,7 +250,7 @@ void
SimpleCPU::activateContext(int thread_num, int delay)
{
assert(thread_num == 0);
- assert(xc);
+ assert(cpuXC);
assert(_status == Idle);
notIdleFraction++;
@@ -245,7 +263,7 @@ void
SimpleCPU::suspendContext(int thread_num)
{
assert(thread_num == 0);
- assert(xc);
+ assert(cpuXC);
assert(_status == Running);
notIdleFraction--;
@@ -338,7 +356,7 @@ SimpleCPU::serialize(ostream &os)
SERIALIZE_ENUM(_status);
SERIALIZE_SCALAR(inst);
nameOut(os, csprintf("%s.xc", name()));
- xc->serialize(os);
+ cpuXC->serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
@@ -350,7 +368,7 @@ SimpleCPU::unserialize(Checkpoint *cp, const string &section)
BaseCPU::unserialize(cp, section);
UNSERIALIZE_ENUM(_status);
UNSERIALIZE_SCALAR(inst);
- xc->unserialize(cp, csprintf("%s.xc", section));
+ cpuXC->unserialize(cp, csprintf("%s.xc", section));
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
}
@@ -371,7 +389,7 @@ SimpleCPU::copySrcTranslate(Addr src)
// Make sure block doesn't span page
if (no_warn &&
- (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) &&
+ (src & PageMask) != ((src + blk_size) & PageMask) &&
(src >> 40) != 0xfffffc) {
warn("Copied block source spans pages %x.", src);
no_warn = false;
@@ -379,17 +397,16 @@ SimpleCPU::copySrcTranslate(Addr src)
memReq->reset(src & ~(blk_size - 1), blk_size);
- // translate to physical address
- Fault fault = xc->translateDataReadReq(req);
-
- assert(fault != Alignment_Fault);
+ // translate to physical address Fault fault = cpuXC->translateDataReadReq(req);
- if (fault == No_Fault) {
- xc->copySrcAddr = src;
- xc->copySrcPhysAddr = memReq->paddr + offset;
+ if (fault == NoFault) {
+ cpuXC->copySrcAddr = src;
+ cpuXC->copySrcPhysAddr = memReq->paddr + offset;
} else {
- xc->copySrcAddr = 0;
- xc->copySrcPhysAddr = 0;
+ assert(!fault->isAlignmentFault());
+
+ cpuXC->copySrcAddr = 0;
+ cpuXC->copySrcPhysAddr = 0;
}
return fault;
#else
@@ -406,12 +423,12 @@ SimpleCPU::copy(Addr dest)
// Only support block sizes of 64 atm.
assert(blk_size == 64);
uint8_t data[blk_size];
- //assert(xc->copySrcAddr);
+ //assert(cpuXC->copySrcAddr);
int offset = dest & (blk_size - 1);
// Make sure block doesn't span page
if (no_warn &&
- (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) &&
+ (dest & PageMask) != ((dest + blk_size) & PageMask) &&
(dest >> 40) != 0xfffffc) {
no_warn = false;
warn("Copied block destination spans pages %x. ", dest);
@@ -419,21 +436,19 @@ SimpleCPU::copy(Addr dest)
memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
- Fault fault = xc->translateDataWriteReq(req);
-
- assert(fault != Alignment_Fault);
+ Fault fault = cpuXC->translateDataWriteReq(req);
- 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;
- xc->mem->read(memReq, data);
+ memReq->paddr = cpuXC->copySrcPhysAddr;
+ cpuXC->mem->read(memReq, data);
memReq->paddr = dest_addr;
- xc->mem->write(memReq, data);
+ cpuXC->mem->write(memReq, data);
if (dcacheInterface) {
memReq->cmd = Copy;
memReq->completionEvent = NULL;
- memReq->paddr = xc->copySrcPhysAddr;
+ memReq->paddr = cpuXC->copySrcPhysAddr;
memReq->dest = dest_addr;
memReq->size = 64;
memReq->time = curTick;
@@ -441,6 +456,9 @@ SimpleCPU::copy(Addr dest)
dcacheInterface->access(memReq);
}
}
+ else
+ assert(!fault->isAlignmentFault());
+
return fault;
#else
panic("copy not implemented");
@@ -480,7 +498,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
data_read_req->time = curTick;
// translate to physical address
- Fault fault = xc->translateDataReadReq(data_read_req);
+ Fault fault = cpuXC->translateDataReadReq(data_read_req);
// Now do the access.
if (fault == No_Fault) {
@@ -527,13 +545,12 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
_status = DcacheMissStall;
} else {
// do functional access
- fault = xc->read(memReq, data);
+ fault = cpuXC->read(memReq, data);
}
-
- } else if(fault == No_Fault) {
+ } else if(fault == NoFault) {
// do functional access
- fault = xc->read(memReq, data);
+ fault = cpuXC->read(memReq, data);
}
*/
@@ -597,8 +614,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
data_write_req->flags = flags;
// translate to physical address
- Fault fault = xc->translateDataWriteReq(data_write_req);
-
+ Fault fault = cpuXC->translateDataWriteReq(data_write_req);
// Now do the access.
if (fault == No_Fault) {
#if SIMPLE_CPU_MEM_TIMING
@@ -618,10 +634,10 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
/*
// do functional access
- if (fault == No_Fault)
- fault = xc->write(memReq, data);
+ if (fault == NoFault)
+ fault = cpuXC->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;
@@ -640,7 +656,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
}
}
*/
- if (res && (fault == No_Fault))
+ if (res && (fault == NoFault))
*res = data_write_pkt->result;
// This will need a new way to tell if it's hooked up to a cache or not.
@@ -699,7 +715,7 @@ SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
Addr
SimpleCPU::dbg_vtophys(Addr addr)
{
- return vtophys(xc, addr);
+ return vtophys(xcProxy, addr);
}
#endif // FULL_SYSTEM
@@ -863,9 +879,9 @@ SimpleCPU::post_interrupt(int int_num, int index)
{
BaseCPU::post_interrupt(int_num, index);
- if (xc->status() == ExecContext::Suspended) {
+ if (cpuXC->status() == ExecContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
- xc->activate();
+ cpuXC->activate();
}
}
#endif // FULL_SYSTEM
@@ -878,30 +894,29 @@ SimpleCPU::tick()
traceData = NULL;
- Fault fault = No_Fault;
+ Fault fault = NoFault;
#if FULL_SYSTEM
- if (checkInterrupts && check_interrupts() && !xc->inPalMode() &&
+ if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() &&
status() != IcacheMissComplete) {
int ipl = 0;
int summary = 0;
checkInterrupts = false;
- IntReg *ipr = xc->regs.ipr;
- if (xc->regs.ipr[TheISA::IPR_SIRR]) {
- for (int i = TheISA::INTLEVEL_SOFTWARE_MIN;
- i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) {
- if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) {
+ if (cpuXC->readMiscReg(IPR_SIRR)) {
+ for (int i = INTLEVEL_SOFTWARE_MIN;
+ i < INTLEVEL_SOFTWARE_MAX; i++) {
+ if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
// See table 4-19 of 21164 hardware reference
- ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1;
+ ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
}
- uint64_t interrupts = xc->cpu->intr_status();
- for (int i = TheISA::INTLEVEL_EXTERNAL_MIN;
- i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) {
+ uint64_t interrupts = cpuXC->cpu->intr_status();
+ for (int i = INTLEVEL_EXTERNAL_MIN;
+ i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
// See table 4-19 of 21164 hardware reference
ipl = i;
@@ -909,24 +924,25 @@ SimpleCPU::tick()
}
}
- if (ipr[TheISA::IPR_ASTRR])
+ if (cpuXC->readMiscReg(IPR_ASTRR))
panic("asynchronous traps not implemented\n");
- if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) {
- ipr[TheISA::IPR_ISR] = summary;
- ipr[TheISA::IPR_INTID] = ipl;
- xc->ev5_trap(Interrupt_Fault);
+ if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) {
+ cpuXC->setMiscReg(IPR_ISR, summary);
+ cpuXC->setMiscReg(IPR_INTID, ipl);
+
+ Fault(new InterruptFault)->invoke(xcProxy);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- ipr[TheISA::IPR_IPLR], ipl, summary);
+ cpuXC->readMiscReg(IPR_IPLR), ipl, summary);
}
}
#endif
// maintain $r0 semantics
- xc->regs.intRegFile[ZeroReg] = 0;
+ cpuXC->setIntReg(ZeroReg, 0);
#ifdef TARGET_ALPHA
- xc->regs.floatRegFile.d[ZeroReg] = 0.0;
+ cpuXC->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
if (status() == IcacheAccessComplete) {
@@ -951,7 +967,7 @@ SimpleCPU::tick()
ifetch_req->size = sizeof(MachInst);
#endif
- ifetch_req->vaddr = xc->regs.pc & ~3;
+ ifetch_req->vaddr = cpuXC->readPC() & ~3;
ifetch_req->time = curTick;
/* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t),
@@ -960,7 +976,7 @@ SimpleCPU::tick()
fault = xc->translateInstReq(ifetch_req);
- if (fault == No_Fault) {
+ if (fault == NoFault) {
#if SIMPLE_CPU_MEM_TIMING
Packet *ifetch_pkt = new Packet;
ifetch_pkt->cmd = Read;
@@ -975,7 +991,7 @@ SimpleCPU::tick()
return;
#endif
/*
- if (icacheInterface && fault == No_Fault) {
+ if (icacheInterface && fault == NoFault) {
memReq->completionEvent = NULL;
memReq->time = curTick;
@@ -999,7 +1015,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++;
@@ -1010,31 +1026,32 @@ SimpleCPU::tick()
// decode the instruction
inst = gtoh(inst);
- curStaticInst = StaticInst<TheISA>::decode(inst);
+ curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC()));
- traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst,
- xc->regs.pc);
+ traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst,
+ cpuXC->readPC());
#if FULL_SYSTEM
- xc->setInst(inst);
+ cpuXC->setInst(inst);
#endif // FULL_SYSTEM
- xc->func_exe_inst++;
+ cpuXC->func_exe_inst++;
fault = curStaticInst->execute(this, traceData);
#if FULL_SYSTEM
- if (xc->fnbin) {
- assert(xc->kernelStats);
- system->kernelBinning->execute(xc, inst);
+ if (system->kernelBinning->fnbin) {
+ assert(kernelStats);
+ system->kernelBinning->execute(xcProxy, inst);
}
- if (xc->profile) {
- bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0;
- xc->profilePC = usermode ? 1 : xc->regs.pc;
- ProfileNode *node = xc->profile->consume(xc, inst);
+ if (cpuXC->profile) {
+ bool usermode =
+ (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
+ cpuXC->profilePC = usermode ? 1 : cpuXC->readPC();
+ ProfileNode *node = cpuXC->profile->consume(xcProxy, inst);
if (node)
- xc->profileNode = node;
+ cpuXC->profileNode = node;
}
#endif
@@ -1053,29 +1070,37 @@ SimpleCPU::tick()
traceData->finalize();
}
- traceFunctions(xc->regs.pc);
+ traceFunctions(cpuXC->readPC());
- } // if (fault == No_Fault)
+ } // if (fault == NoFault)
- if (fault != No_Fault) {
+ if (fault != NoFault) {
#if FULL_SYSTEM
- xc->ev5_trap(fault);
+ fault->invoke(xcProxy);
#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc);
+ fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
#endif // FULL_SYSTEM
}
else {
+#if THE_ISA != MIPS_ISA
// go to the next instruction
- xc->regs.pc = xc->regs.npc;
- xc->regs.npc += sizeof(MachInst);
+ cpuXC->setPC(cpuXC->readNextPC());
+ cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
+#else
+ // go to the next instruction
+ cpuXC->setPC(cpuXC->readNextPC());
+ cpuXC->setNextPC(cpuXC->readNextNPC());
+ cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
+#endif
+
}
#if FULL_SYSTEM
Addr oldpc;
do {
- oldpc = xc->regs.pc;
- system->pcEventQueue.service(xc);
- } while (oldpc != xc->regs.pc);
+ oldpc = cpuXC->readPC();
+ system->pcEventQueue.service(xcProxy);
+ } while (oldpc != cpuXC->readPC());
#endif
assert(status() == Running ||
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
index ca10134f7..fbfae950f 100644
--- a/cpu/simple/cpu.hh
+++ b/cpu/simple/cpu.hh
@@ -32,7 +32,7 @@
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/pc_event.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
@@ -57,6 +57,7 @@ class Process;
#endif // FULL_SYSTEM
+class ExecContext;
class MemInterface;
class Checkpoint;
@@ -76,6 +77,9 @@ namespace Trace {
class SimpleCPU : public BaseCPU
{
+ protected:
+ typedef TheISA::MachInst MachInst;
+ typedef TheISA::MiscReg MiscReg;
class CpuPort : public Port
{
@@ -106,6 +110,7 @@ class SimpleCPU : public BaseCPU
public:
// main simulation loop (one cycle)
void tick();
+ virtual void init();
private:
struct TickEvent : public Event
@@ -184,7 +189,9 @@ class SimpleCPU : public BaseCPU
public:
// execution context
- ExecContext *xc;
+ CPUExecContext *cpuXC;
+
+ ExecContext *xcProxy;
void switchOut(Sampler *s);
void takeOverFrom(BaseCPU *oldCPU);
@@ -214,7 +221,7 @@ class SimpleCPU : public BaseCPU
// the next switchover
Sampler *sampler;
- StaticInstPtr<TheISA> curStaticInst;
+ StaticInstPtr curStaticInst;
Status status() const { return _status; }
@@ -310,76 +317,88 @@ class SimpleCPU : public BaseCPU
// storage (which is pretty hard to imagine they would have reason
// to do).
- uint64_t readIntReg(const StaticInst<TheISA> *si, int idx)
+ uint64_t readIntReg(const StaticInst *si, int idx)
{
- return xc->readIntReg(si->srcRegIdx(idx));
+ return cpuXC->readIntReg(si->srcRegIdx(idx));
}
- float readFloatRegSingle(const StaticInst<TheISA> *si, int idx)
+ float readFloatRegSingle(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegSingle(reg_idx);
+ return cpuXC->readFloatRegSingle(reg_idx);
}
- double readFloatRegDouble(const StaticInst<TheISA> *si, int idx)
+ double readFloatRegDouble(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegDouble(reg_idx);
+ return cpuXC->readFloatRegDouble(reg_idx);
}
- uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx)
+ uint64_t readFloatRegInt(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegInt(reg_idx);
+ return cpuXC->readFloatRegInt(reg_idx);
}
- void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val)
+ void setIntReg(const StaticInst *si, int idx, uint64_t val)
{
- xc->setIntReg(si->destRegIdx(idx), val);
+ cpuXC->setIntReg(si->destRegIdx(idx), val);
}
- void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val)
+ void setFloatRegSingle(const StaticInst *si, int idx, float val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegSingle(reg_idx, val);
+ cpuXC->setFloatRegSingle(reg_idx, val);
}
- void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val)
+ void setFloatRegDouble(const StaticInst *si, int idx, double val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegDouble(reg_idx, val);
+ cpuXC->setFloatRegDouble(reg_idx, val);
}
- void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val)
+ void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegInt(reg_idx, val);
+ cpuXC->setFloatRegInt(reg_idx, val);
}
- uint64_t readPC() { return xc->readPC(); }
- void setNextPC(uint64_t val) { xc->setNextPC(val); }
+ uint64_t readPC() { return cpuXC->readPC(); }
+ void setNextPC(uint64_t val) { cpuXC->setNextPC(val); }
+
+ MiscReg readMiscReg(int misc_reg)
+ {
+ return cpuXC->readMiscReg(misc_reg);
+ }
- uint64_t readUniq() { return xc->readUniq(); }
- void setUniq(uint64_t val) { xc->setUniq(val); }
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return cpuXC->readMiscRegWithEffect(misc_reg, fault);
+ }
- uint64_t readFpcr() { return xc->readFpcr(); }
- void setFpcr(uint64_t val) { xc->setFpcr(val); }
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ return cpuXC->setMiscReg(misc_reg, val);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return cpuXC->setMiscRegWithEffect(misc_reg, 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(); }
- 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); }
- bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
+ Fault hwrei() { return cpuXC->hwrei(); }
+ int readIntrFlag() { return cpuXC->readIntrFlag(); }
+ void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
+ bool inPalMode() { return cpuXC->inPalMode(); }
+ void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
+ bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
#else
- void syscall() { xc->syscall(); }
+ void syscall() { cpuXC->syscall(); }
#endif
- bool misspeculating() { return xc->misspeculating(); }
- ExecContext *xcBase() { return xc; }
+ bool misspeculating() { return cpuXC->misspeculating(); }
+ ExecContext *xcBase() { return xcProxy; }
};
#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
diff --git a/cpu/static_inst.cc b/cpu/static_inst.cc
index 54bd9914e..c307dc6fc 100644
--- a/cpu/static_inst.cc
+++ b/cpu/static_inst.cc
@@ -30,19 +30,13 @@
#include "cpu/static_inst.hh"
#include "sim/root.hh"
-template <class ISA>
-StaticInstPtr<ISA> StaticInst<ISA>::nullStaticInstPtr;
-
-template <class ISA>
-typename StaticInst<ISA>::DecodeCache StaticInst<ISA>::decodeCache;
+StaticInstPtr StaticInst::nullStaticInstPtr;
// Define the decode cache hash map.
-template StaticInst<AlphaISA>::DecodeCache
-StaticInst<AlphaISA>::decodeCache;
+StaticInst::DecodeCache StaticInst::decodeCache;
-template <class ISA>
void
-StaticInst<ISA>::dumpDecodeCacheStats()
+StaticInst::dumpDecodeCacheStats()
{
using namespace std;
@@ -62,13 +56,8 @@ StaticInst<ISA>::dumpDecodeCacheStats()
}
}
-
-template StaticInstPtr<AlphaISA>
-StaticInst<AlphaISA>::nullStaticInstPtr;
-
-template <class ISA>
bool
-StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const
+StaticInst::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const
{
if (isDirectCtrl()) {
tgt = branchTarget(pc);
@@ -83,6 +72,3 @@ StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const
return false;
}
-
-// force instantiation of template function(s) above
-template class StaticInst<AlphaISA>;
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 09eb7efbf..2ed2fe61c 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -36,7 +36,7 @@
#include "base/refcnt.hh"
#include "cpu/op_class.hh"
#include "sim/host.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/isa_traits.hh"
// forward declarations
struct AlphaSimpleImpl;
@@ -109,10 +109,14 @@ class StaticInstBase : public RefCounted
IsCall, ///< Subroutine call.
IsReturn, ///< Subroutine return.
+ IsCondDelaySlot,///< Conditional Delay-Slot Instruction
+
IsThreadSync, ///< Thread synchronization operation.
IsSerializing, ///< Serializes pipeline: won't execute until all
/// older instructions have committed.
+ IsSerializeBefore,
+ IsSerializeAfter,
IsMemBarrier, ///< Is a memory barrier
IsWriteBarrier, ///< Is a write barrier
@@ -196,7 +200,11 @@ class StaticInstBase : public RefCounted
bool isUncondCtrl() const { return flags[IsUncondControl]; }
bool isThreadSync() const { return flags[IsThreadSync]; }
- bool isSerializing() const { return flags[IsSerializing]; }
+ bool isSerializing() const { return flags[IsSerializing] ||
+ flags[IsSerializeBefore] ||
+ flags[IsSerializeAfter]; }
+ bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
+ bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
bool isMemBarrier() const { return flags[IsMemBarrier]; }
bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
@@ -208,7 +216,6 @@ class StaticInstBase : public RefCounted
// forward declaration
-template <class ISA>
class StaticInstPtr;
/**
@@ -218,21 +225,20 @@ class StaticInstPtr;
* that are generic across all ISAs but that differ in details
* according to the specific ISA being used.
*/
-template <class ISA>
class StaticInst : public StaticInstBase
{
public:
/// Binary machine instruction type.
- typedef typename ISA::MachInst MachInst;
- /// Memory address type.
- typedef typename ISA::Addr Addr;
+ typedef TheISA::MachInst MachInst;
+ /// Binary extended machine instruction type.
+ typedef TheISA::ExtMachInst ExtMachInst;
/// Logical register index type.
- typedef typename ISA::RegIndex RegIndex;
+ typedef TheISA::RegIndex RegIndex;
enum {
- MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
};
@@ -247,7 +253,7 @@ class StaticInst : public StaticInstBase
/// Pointer to a statically allocated "null" instruction object.
/// Used to give eaCompInst() and memAccInst() something to return
/// when called on non-memory instructions.
- static StaticInstPtr<ISA> nullStaticInstPtr;
+ static StaticInstPtr nullStaticInstPtr;
/**
* Memory references only: returns "fake" instruction representing
@@ -256,7 +262,7 @@ class StaticInst : public StaticInstBase
* just the EA computation.
*/
virtual const
- StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; }
+ StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
/**
* Memory references only: returns "fake" instruction representing
@@ -265,10 +271,10 @@ class StaticInst : public StaticInstBase
* just the memory access (not the EA computation).
*/
virtual const
- StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; }
+ StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
/// The binary machine instruction.
- const MachInst machInst;
+ const ExtMachInst machInst;
protected:
@@ -298,7 +304,7 @@ class StaticInst : public StaticInstBase
generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
/// Constructor.
- StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass)
+ StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
: StaticInstBase(__opClass),
machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
{
@@ -312,7 +318,11 @@ class StaticInst : public StaticInstBase
delete cachedDisassembly;
}
-#include "static_inst_impl.hh"
+/**
+ * The execute() signatures are auto-generated by scons based on the
+ * set of CPU models we are compiling in today.
+ */
+#include "cpu/static_inst_exec_sigs.hh"
/**
* Return the target address for a PC-relative branch.
@@ -364,7 +374,7 @@ class StaticInst : public StaticInstBase
/// Decoded instruction cache type.
/// For now we're using a generic hash_map; this seems to work
/// pretty well.
- typedef m5::hash_map<MachInst, StaticInstPtr<ISA> > DecodeCache;
+ typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
/// A cache of decoded instruction objects.
static DecodeCache decodeCache;
@@ -378,63 +388,40 @@ class StaticInst : public StaticInstBase
/// Decode a machine instruction.
/// @param mach_inst The binary instruction to decode.
/// @retval A pointer to the corresponding StaticInst object.
- static
- StaticInstPtr<ISA> decode(MachInst mach_inst)
- {
-#ifdef DECODE_CACHE_HASH_STATS
- // Simple stats on decode hash_map. Turns out the default
- // hash function is as good as anything I could come up with.
- const int dump_every_n = 10000000;
- static int decodes_til_dump = dump_every_n;
-
- if (--decodes_til_dump == 0) {
- dumpDecodeCacheStats();
- decodes_til_dump = dump_every_n;
- }
-#endif
-
- typename DecodeCache::iterator iter = decodeCache.find(mach_inst);
- if (iter != decodeCache.end()) {
- return iter->second;
- }
-
- StaticInstPtr<ISA> si = ISA::decodeInst(mach_inst);
- decodeCache[mach_inst] = si;
- return si;
- }
+ //This is defined as inline below.
+ static StaticInstPtr decode(ExtMachInst mach_inst);
};
typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
/// Reference-counted pointer to a StaticInst object.
-/// This type should be used instead of "StaticInst<ISA> *" so that
+/// This type should be used instead of "StaticInst *" so that
/// StaticInst objects can be properly reference-counted.
-template <class ISA>
-class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
+class StaticInstPtr : public RefCountingPtr<StaticInst>
{
public:
/// Constructor.
StaticInstPtr()
- : RefCountingPtr<StaticInst<ISA> >()
+ : RefCountingPtr<StaticInst>()
{
}
- /// Conversion from "StaticInst<ISA> *".
- StaticInstPtr(StaticInst<ISA> *p)
- : RefCountingPtr<StaticInst<ISA> >(p)
+ /// Conversion from "StaticInst *".
+ StaticInstPtr(StaticInst *p)
+ : RefCountingPtr<StaticInst>(p)
{
}
/// Copy constructor.
StaticInstPtr(const StaticInstPtr &r)
- : RefCountingPtr<StaticInst<ISA> >(r)
+ : RefCountingPtr<StaticInst>(r)
{
}
/// Construct directly from machine instruction.
- /// Calls StaticInst<ISA>::decode().
- StaticInstPtr(typename ISA::MachInst mach_inst)
- : RefCountingPtr<StaticInst<ISA> >(StaticInst<ISA>::decode(mach_inst))
+ /// Calls StaticInst::decode().
+ StaticInstPtr(TheISA::ExtMachInst mach_inst)
+ : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
{
}
@@ -445,4 +432,29 @@ class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
}
};
+inline StaticInstPtr
+StaticInst::decode(StaticInst::ExtMachInst mach_inst)
+{
+#ifdef DECODE_CACHE_HASH_STATS
+ // Simple stats on decode hash_map. Turns out the default
+ // hash function is as good as anything I could come up with.
+ const int dump_every_n = 10000000;
+ static int decodes_til_dump = dump_every_n;
+
+ if (--decodes_til_dump == 0) {
+ dumpDecodeCacheStats();
+ decodes_til_dump = dump_every_n;
+ }
+#endif
+
+ DecodeCache::iterator iter = decodeCache.find(mach_inst);
+ if (iter != decodeCache.end()) {
+ return iter->second;
+ }
+
+ StaticInstPtr si = TheISA::decodeInst(mach_inst);
+ decodeCache[mach_inst] = si;
+ return si;
+}
+
#endif // __CPU_STATIC_INST_HH__
diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh
index faec73138..a16a08085 100644
--- a/cpu/trace/reader/itx_reader.hh
+++ b/cpu/trace/reader/itx_reader.hh
@@ -46,6 +46,7 @@
*/
class ITXReader : public MemTraceReader
{
+ private:
/** Trace file. */
FILE *trace;
diff --git a/dev/alpha_access.h b/dev/alpha_access.h
index a20a05535..5a1df6f39 100644
--- a/dev/alpha_access.h
+++ b/dev/alpha_access.h
@@ -33,7 +33,7 @@
* System Console Memory Mapped Register Definition
*/
-#define ALPHA_ACCESS_VERSION (1303)
+#define ALPHA_ACCESS_VERSION (1305)
#ifdef CONSOLE
typedef unsigned uint32_t;
@@ -67,9 +67,7 @@ struct AlphaAccess
uint64_t inputChar; // 68: Placeholder for input
// MP boot
- uint64_t bootStrapImpure; // 70:
- uint32_t bootStrapCPU; // 78:
- uint32_t align2; // 7C: Dummy placeholder for alignment
+ uint64_t cpuStack[64]; // 70:
};
#endif // __ALPHA_ACCESS_H__
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 61b444628..6ca5e3a06 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -34,6 +34,7 @@
#include <cstdio>
#include <string>
+#include "arch/alpha/system.hh"
#include "base/inifile.hh"
#include "base/str.hh"
#include "base/trace.hh"
@@ -50,12 +51,12 @@
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
-#include "sim/system.hh"
using namespace std;
+using namespace AlphaISA;
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
- System *s, BaseCPU *c, Platform *p,
+ AlphaSystem *s, BaseCPU *c, Platform *p,
MemoryController *mmu, Addr a,
HierParams *hier, Bus *pio_bus)
: PioDevice(name, p), disk(d), console(cons), system(s), cpu(c), addr(a)
@@ -80,9 +81,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
alphaAccess->diskOperation = 0;
alphaAccess->outputChar = 0;
alphaAccess->inputChar = 0;
- alphaAccess->bootStrapImpure = 0;
- alphaAccess->bootStrapCPU = 0;
- alphaAccess->align2 = 0;
+ bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
system->setAlphaAccess(addr);
}
@@ -122,9 +121,6 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data)
case offsetof(AlphaAccess, numCPUs):
*(uint32_t*)data = alphaAccess->numCPUs;
break;
- case offsetof(AlphaAccess, bootStrapCPU):
- *(uint32_t*)data = alphaAccess->bootStrapCPU;
- break;
case offsetof(AlphaAccess, intrClockFrequency):
*(uint32_t*)data = alphaAccess->intrClockFrequency;
break;
@@ -175,18 +171,21 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data)
case offsetof(AlphaAccess, outputChar):
*(uint64_t*)data = alphaAccess->outputChar;
break;
- case offsetof(AlphaAccess, bootStrapImpure):
- *(uint64_t*)data = alphaAccess->bootStrapImpure;
- break;
default:
- panic("Unknown 64bit access, %#x\n", daddr);
+ int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
+ sizeof(alphaAccess->cpuStack[0]);
+
+ if (cpunum >= 0 && cpunum < 64)
+ *(uint64_t*)data = alphaAccess->cpuStack[cpunum];
+ else
+ panic("Unknown 64bit access, %#x\n", daddr);
}
break;
default:
- return Machine_Check_Fault;
+ return genMachineCheckFault();
}
- return No_Fault;
+ return NoFault;
}
Fault
@@ -203,7 +202,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
val = *(uint64_t *)data;
break;
default:
- return Machine_Check_Fault;
+ return genMachineCheckFault();
}
Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
@@ -239,27 +238,21 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
console->out((char)(val & 0xff));
break;
- case offsetof(AlphaAccess, bootStrapImpure):
- alphaAccess->bootStrapImpure = val;
- break;
-
- case offsetof(AlphaAccess, bootStrapCPU):
- warn("%d: Trying to launch another CPU!", curTick);
- assert(val > 0 && "Must not access primary cpu");
-
- other_xc = req->xc->system->execContexts[val];
- other_xc->regs.intRegFile[16] = val;
- other_xc->regs.ipr[TheISA::IPR_PALtemp16] = val;
- other_xc->regs.intRegFile[0] = val;
- other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
other_xc->activate(); //Start the cpu
break;
default:
- return Machine_Check_Fault;
+ int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
+ sizeof(alphaAccess->cpuStack[0]);
+ warn("%d: Trying to launch CPU number %d!", curTick, cpunum);
+ assert(val > 0 && "Must not access primary cpu");
+ if (cpunum >= 0 && cpunum < 64)
+ alphaAccess->cpuStack[cpunum] = val;
+ else
+ panic("Unknown 64bit access, %#x\n", daddr);
}
- return No_Fault;
+ return NoFault;
}
Tick
@@ -287,8 +280,7 @@ AlphaConsole::Access::serialize(ostream &os)
SERIALIZE_SCALAR(diskOperation);
SERIALIZE_SCALAR(outputChar);
SERIALIZE_SCALAR(inputChar);
- SERIALIZE_SCALAR(bootStrapImpure);
- SERIALIZE_SCALAR(bootStrapCPU);
+ SERIALIZE_ARRAY(cpuStack,64);
}
void
@@ -310,8 +302,7 @@ AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(diskOperation);
UNSERIALIZE_SCALAR(outputChar);
UNSERIALIZE_SCALAR(inputChar);
- UNSERIALIZE_SCALAR(bootStrapImpure);
- UNSERIALIZE_SCALAR(bootStrapCPU);
+ UNSERIALIZE_ARRAY(cpuStack, 64);
}
void
@@ -332,7 +323,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
SimObjectParam<SimpleDisk *> disk;
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
- SimObjectParam<System *> system;
+ SimObjectParam<AlphaSystem *> system;
SimObjectParam<BaseCPU *> cpu;
SimObjectParam<Platform *> platform;
SimObjectParam<Bus*> pio_bus;
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index 74ad795f0..f63c6ad7e 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -41,8 +41,9 @@
class BaseCPU;
class SimConsole;
-class System;
+class AlphaSystem;
class SimpleDisk;
+class MemoryController;
/**
* Memory mapped interface to the system console. This device
@@ -90,18 +91,18 @@ class AlphaConsole : public PioDevice
SimConsole *console;
/** a pointer to the system we are running in */
- System *system;
+ AlphaSystem *system;
/** a pointer to the CPU boot cpu */
BaseCPU *cpu;
Addr addr;
- static const Addr size = 0x80; // equal to sizeof(alpha_access);
+ static const Addr size = sizeof(struct AlphaAccess);
public:
/** Standard Constructor */
AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d,
- System *s, BaseCPU *c, Platform *platform,
+ AlphaSystem *s, BaseCPU *c, Platform *platform,
MemoryController *mmu, Addr addr,
HierParams *hier, Bus *pio_bus);
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 52c538707..87d683a5d 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -46,6 +46,7 @@
#include "sim/system.hh"
using namespace std;
+using namespace TheISA;
BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *pio_bus, const string &devicename)
@@ -66,14 +67,14 @@ BadDevice::read(MemReqPtr &req, uint8_t *data)
{
panic("Device %s not imlpmented\n", devname);
- return No_Fault;
+ return NoFault;
}
Fault
BadDevice::write(MemReqPtr &req, const uint8_t *data)
{
panic("Device %s not imlpmented\n", devname);
- return No_Fault;
+ return NoFault;
}
Tick
diff --git a/dev/baddev.hh b/dev/baddev.hh
index c2a204c05..189f28331 100644
--- a/dev/baddev.hh
+++ b/dev/baddev.hh
@@ -37,6 +37,8 @@
#include "base/range.hh"
#include "dev/io_device.hh"
+class MemoryController;
+
/**
* BadDevice
* This device just panics when accessed. It is supposed to warn
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..56682a224 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -48,6 +48,7 @@
#include "sim/sim_object.hh"
using namespace std;
+using namespace TheISA;
////
// Initialization and destruction
@@ -401,7 +402,7 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
parseAddr(req->paddr, offset, channel, reg_type);
if (!io_enabled)
- return No_Fault;
+ return NoFault;
switch (reg_type) {
case BMI_BLOCK:
@@ -457,7 +458,7 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
offset, req->size, *(uint32_t*)data);
- return No_Fault;
+ return NoFault;
}
Fault
@@ -472,12 +473,12 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
parseAddr(req->paddr, offset, channel, reg_type);
if (!io_enabled)
- return No_Fault;
+ return NoFault;
switch (reg_type) {
case BMI_BLOCK:
if (!bm_enabled)
- return No_Fault;
+ return NoFault;
switch (offset) {
// Bus master IDE command register
@@ -627,7 +628,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
offset, req->size, *(uint32_t*)data);
- return No_Fault;
+ return NoFault;
}
////
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index ea8f151c0..41400c590 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -50,9 +50,10 @@
#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;
+using namespace TheISA;
IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
int id, Tick delay)
diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc
index e2802eaa9..2afebbded 100644
--- a/dev/isa_fake.cc
+++ b/dev/isa_fake.cc
@@ -45,6 +45,7 @@
#include "sim/system.hh"
using namespace std;
+using namespace TheISA;
IsaFake::IsaFake(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *pio_bus, Addr size)
@@ -73,23 +74,23 @@ IsaFake::read(MemReqPtr &req, uint8_t *data)
case sizeof(uint64_t):
*(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL;
- return No_Fault;
+ return NoFault;
case sizeof(uint32_t):
*(uint32_t*)data = 0xFFFFFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint16_t):
*(uint16_t*)data = 0xFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint8_t):
*(uint8_t*)data = 0xFF;
- return No_Fault;
+ return NoFault;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
DPRINTFN("Isa FakeSMC ERROR: read daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
Fault
@@ -100,7 +101,7 @@ IsaFake::write(MemReqPtr &req, const uint8_t *data)
//:Addr daddr = (req->paddr & addr_mask) >> 6;
- return No_Fault;
+ return NoFault;
}
Tick
diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh
index 290b24b54..73e40c681 100644
--- a/dev/isa_fake.hh
+++ b/dev/isa_fake.hh
@@ -37,6 +37,8 @@
#include "base/range.hh"
#include "dev/io_device.hh"
+class MemoryController;
+
/**
* IsaFake is a device that returns -1 on all reads and
* accepts all writes. It is meant to be placed at an address range
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index 9010850ab..ed8c794f9 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -49,7 +49,7 @@
#include "sim/debug.hh"
#include "sim/host.hh"
#include "sim/stats.hh"
-#include "targetarch/vtophys.hh"
+#include "arch/vtophys.hh"
const char *NsRxStateStrings[] =
{
@@ -84,6 +84,7 @@ const char *NsDmaState[] =
using namespace std;
using namespace Net;
+using namespace TheISA;
///////////////////////////////////////////////////////////////////////
//
@@ -130,8 +131,6 @@ NSGigE::NSGigE(Params *p)
} else if (p->payload_bus)
panic("Must define a header bus if defining a payload bus");
- pioDelayWrite = p->pio_delay_write && pioInterface;
-
intrDelay = p->intr_delay;
dmaReadDelay = p->dma_read_delay;
dmaWriteDelay = p->dma_write_delay;
@@ -575,14 +574,14 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
readConfig(daddr & 0xff, req->size, data);
- return No_Fault;
+ return NoFault;
} else if (daddr >= MIB_START && daddr <= MIB_END) {
// don't implement all the MIB's. hopefully the kernel
// doesn't actually DEPEND upon their values
// MIB are just hardware stats keepers
uint32_t &reg = *(uint32_t *) data;
reg = 0;
- return No_Fault;
+ return NoFault;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
@@ -768,6 +767,8 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
reg |= M5REG_RX_THREAD;
if (params()->tx_thread)
reg |= M5REG_TX_THREAD;
+ if (params()->rss)
+ reg |= M5REG_RSS;
break;
default:
@@ -784,7 +785,7 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
daddr, req->size);
}
- return No_Fault;
+ return NoFault;
}
Fault
@@ -800,17 +801,10 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
writeConfig(daddr & 0xff, req->size, data);
- return No_Fault;
+ return NoFault;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
- if (pioDelayWrite) {
- int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
- if (cpu >= writeQueue.size())
- writeQueue.resize(cpu + 1);
- writeQueue[cpu].push_back(RegWriteData(daddr, *(uint32_t *)data));
- }
-
if (req->size == sizeof(uint32_t)) {
uint32_t reg = *(uint32_t *)data;
uint16_t rfaddr;
@@ -823,24 +817,20 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
if (reg & CR_TXD) {
txEnable = false;
} else if (reg & CR_TXE) {
- if (!pioDelayWrite) {
- txEnable = true;
+ txEnable = true;
- // the kernel is enabling the transmit machine
- if (txState == txIdle)
- txKick();
- }
+ // the kernel is enabling the transmit machine
+ if (txState == txIdle)
+ txKick();
}
if (reg & CR_RXD) {
rxEnable = false;
} else if (reg & CR_RXE) {
- if (!pioDelayWrite) {
- rxEnable = true;
+ rxEnable = true;
- if (rxState == rxIdle)
- rxKick();
- }
+ if (rxState == rxIdle)
+ rxKick();
}
if (reg & CR_TXR)
@@ -1203,7 +1193,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
panic("Invalid Request Size");
}
- return No_Fault;
+ return NoFault;
}
void
@@ -2948,38 +2938,9 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
Tick
NSGigE::cacheAccess(MemReqPtr &req)
{
- Addr daddr = req->paddr & 0xfff;
DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
- req->paddr, daddr);
-
- if (!pioDelayWrite || !req->cmd.isWrite())
- return curTick + pioLatency;
-
- int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
- std::list<RegWriteData> &wq = writeQueue[cpu];
- if (wq.empty())
- panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr);
-
- const RegWriteData &data = wq.front();
- if (data.daddr != daddr)
- panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
- cpu, data.daddr, daddr);
-
- if (daddr == CR) {
- if ((data.value & (CR_TXD | CR_TXE)) == CR_TXE) {
- txEnable = true;
- if (txState == txIdle)
- txKick();
- }
-
- if ((data.value & (CR_RXD | CR_RXE)) == CR_RXE) {
- rxEnable = true;
- if (rxState == rxIdle)
- rxKick();
- }
- }
+ req->paddr, req->paddr & 0xfff);
- wq.pop_front();
return curTick + pioLatency;
}
@@ -3039,7 +3000,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> dma_write_factor;
Param<bool> dma_no_allocate;
Param<Tick> pio_latency;
- Param<bool> pio_delay_write;
Param<Tick> intr_delay;
Param<Tick> rx_delay;
@@ -3051,6 +3011,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<string> hardware_address;
Param<bool> rx_thread;
Param<bool> tx_thread;
+ Param<bool> rss;
END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
@@ -3080,7 +3041,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"),
INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"),
- INIT_PARAM(pio_delay_write, ""),
INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
INIT_PARAM(rx_delay, "Receive Delay"),
@@ -3091,7 +3051,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(rx_filter, "Enable Receive Filter"),
INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
INIT_PARAM(rx_thread, ""),
- INIT_PARAM(tx_thread, "")
+ INIT_PARAM(tx_thread, ""),
+ INIT_PARAM(rss, "")
END_INIT_SIM_OBJECT_PARAMS(NSGigE)
@@ -3125,7 +3086,6 @@ CREATE_SIM_OBJECT(NSGigE)
params->dma_write_factor = dma_write_factor;
params->dma_no_allocate = dma_no_allocate;
params->pio_latency = pio_latency;
- params->pio_delay_write = pio_delay_write;
params->intr_delay = intr_delay;
params->rx_delay = rx_delay;
@@ -3137,6 +3097,7 @@ CREATE_SIM_OBJECT(NSGigE)
params->eaddr = hardware_address;
params->rx_thread = rx_thread;
params->tx_thread = tx_thread;
+ params->rss = rss;
return new NSGigE(params);
}
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index ade7e32e6..59c55056e 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -170,9 +170,6 @@ class NSGigE : public PciDev
static const Addr size = sizeof(dp_regs);
protected:
- typedef std::deque<PacketPtr> pktbuf_t;
- typedef pktbuf_t::iterator pktiter_t;
-
/** device register file */
dp_regs regs;
dp_rom rom;
@@ -239,15 +236,6 @@ class NSGigE : public PciDev
uint32_t rxDescCnt;
DmaState rxDmaState;
- struct RegWriteData {
- Addr daddr;
- uint32_t value;
- RegWriteData(Addr da, uint32_t val) : daddr(da), value(val) {}
- };
-
- std::vector<std::list<RegWriteData> > writeQueue;
- bool pioDelayWrite;
-
bool extstsEnable;
/** EEPROM State Machine */
@@ -385,7 +373,6 @@ class NSGigE : public PciDev
Tick tx_delay;
Tick rx_delay;
Tick pio_latency;
- bool pio_delay_write;
bool dma_desc_free;
bool dma_data_free;
Tick dma_read_delay;
@@ -398,6 +385,7 @@ class NSGigE : public PciDev
uint32_t rx_fifo_size;
bool rx_thread;
bool tx_thread;
+ bool rss;
bool dma_no_allocate;
};
diff --git a/dev/ns_gige_reg.h b/dev/ns_gige_reg.h
index eadc60d03..5f6fa2cc5 100644
--- a/dev/ns_gige_reg.h
+++ b/dev/ns_gige_reg.h
@@ -306,6 +306,7 @@
/* M5 control register */
#define M5REG_RESERVED 0xfffffffc
+#define M5REG_RSS 0x00000004
#define M5REG_RX_THREAD 0x00000002
#define M5REG_TX_THREAD 0x00000001
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 396e130af..d55084fa5 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -47,6 +47,7 @@
#include "sim/system.hh"
using namespace std;
+using namespace TheISA;
PciConfigAll::PciConfigAll(const string &name,
Addr a, MemoryController *mmu,
@@ -112,16 +113,16 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
switch (req->size) {
// case sizeof(uint64_t):
// *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF;
- // return No_Fault;
+ // return NoFault;
case sizeof(uint32_t):
*(uint32_t*)data = 0xFFFFFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint16_t):
*(uint16_t*)data = 0xFFFF;
- return No_Fault;
+ return NoFault;
case sizeof(uint8_t):
*(uint8_t*)data = 0xFF;
- return No_Fault;
+ return NoFault;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
@@ -131,7 +132,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
case sizeof(uint16_t):
case sizeof(uint8_t):
devices[device][func]->readConfig(reg, req->size, data);
- return No_Fault;
+ return NoFault;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
@@ -140,7 +141,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n",
daddr, req->size);
- return No_Fault;
+ return NoFault;
}
Fault
@@ -164,7 +165,7 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
devices[device][func]->writeConfig(reg, req->size, data);
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index 1d9ea137d..a05ee3803 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -72,11 +72,11 @@ PciDev::PciDev(Params *p)
Fault
PciDev::read(MemReqPtr &req, uint8_t *data)
-{ return No_Fault; }
+{ return NoFault; }
Fault
PciDev::write(MemReqPtr &req, const uint8_t *data)
-{ return No_Fault; }
+{ return NoFault; }
Fault
PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index efc805b3f..bdfc6b932 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -260,6 +260,7 @@ class PciDev : public DmaDevice
inline Fault
PciDev::readBar(MemReqPtr &req, uint8_t *data)
{
+ using namespace TheISA;
if (isBAR(req->paddr, 0))
return readBar0(req, req->paddr - BARAddrs[0], data);
if (isBAR(req->paddr, 1))
@@ -272,12 +273,13 @@ 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 genMachineCheckFault();
}
inline Fault
PciDev::writeBar(MemReqPtr &req, const uint8_t *data)
{
+ using namespace TheISA;
if (isBAR(req->paddr, 0))
return writeBar0(req, req->paddr - BARAddrs[0], data);
if (isBAR(req->paddr, 1))
@@ -290,7 +292,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 genMachineCheckFault();
}
#endif // __DEV_PCIDEV_HH__
diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc
index b4fab2d6f..639009be9 100644
--- a/dev/pktfifo.cc
+++ b/dev/pktfifo.cc
@@ -31,6 +31,36 @@
using namespace std;
+bool
+PacketFifo::copyout(void *dest, int offset, int len)
+{
+ char *data = (char *)dest;
+ if (offset + len >= size())
+ return false;
+
+ list<PacketPtr>::iterator p = fifo.begin();
+ list<PacketPtr>::iterator end = fifo.end();
+ while (len > 0) {
+ while (offset >= (*p)->length) {
+ offset -= (*p)->length;
+ ++p;
+ }
+
+ if (p == end)
+ panic("invalid fifo");
+
+ int size = min((*p)->length - offset, len);
+ memcpy(data, (*p)->data, size);
+ offset = 0;
+ len -= size;
+ data += size;
+ ++p;
+ }
+
+ return true;
+}
+
+
void
PacketFifo::serialize(const string &base, ostream &os)
{
@@ -40,8 +70,8 @@ PacketFifo::serialize(const string &base, ostream &os)
paramOut(os, base + ".packets", fifo.size());
int i = 0;
- std::list<PacketPtr>::iterator p = fifo.begin();
- std::list<PacketPtr>::iterator end = fifo.end();
+ list<PacketPtr>::iterator p = fifo.begin();
+ list<PacketPtr>::iterator end = fifo.end();
while (p != end) {
(*p)->serialize(csprintf("%s.packet%d", base, i), os);
++p;
diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh
index e63fd291f..e245840a8 100644
--- a/dev/pktfifo.hh
+++ b/dev/pktfifo.hh
@@ -127,6 +127,35 @@ class PacketFifo
fifo.erase(i);
}
+ bool copyout(void *dest, int offset, int len);
+
+ int countPacketsBefore(iterator end)
+ {
+ iterator i = fifo.begin();
+ int count = 0;
+
+ while (i != end) {
+ ++count;
+ ++i;
+ }
+
+ return count;
+ }
+
+ int countPacketsAfter(iterator i)
+ {
+ iterator end = fifo.end();
+ int count = 0;
+
+ while (i != end) {
+ ++count;
+ ++i;
+ }
+
+ return count;
+ }
+
+
/**
* Serialization stuff
*/
diff --git a/dev/platform.cc b/dev/platform.cc
index 58f94db7b..5b667b12c 100644
--- a/dev/platform.cc
+++ b/dev/platform.cc
@@ -31,6 +31,7 @@
#include "sim/sim_exit.hh"
using namespace std;
+using namespace TheISA;
Platform::Platform(const string &name, IntrControl *intctrl, PciConfigAll *pci)
: SimObject(name), intrctrl(intctrl), pciconfig(pci)
diff --git a/dev/platform.hh b/dev/platform.hh
index ff37ee71a..2c37048d4 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..57f81c5a9 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;
@@ -44,19 +44,19 @@ class PhysicalMemory;
*/
class SimpleDisk : public SimObject
{
-public:
- typedef uint64_t baddr_t;
+ public:
+ typedef uint64_t baddr_t;
-protected:
- PhysicalMemory *physmem;
- DiskImage *image;
+ protected:
+ PhysicalMemory *physmem;
+ DiskImage *image;
-public:
- SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img);
- ~SimpleDisk();
+ public:
+ SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img);
+ ~SimpleDisk();
- void read(Addr addr, baddr_t block, int count) const;
- void write(Addr addr, baddr_t block, int count);
+ void read(Addr addr, baddr_t block, int count) const;
+ void write(Addr addr, baddr_t block, int count);
};
#endif // __DEV_SIMPLE_DISK_HH__
diff --git a/dev/sinic.cc b/dev/sinic.cc
index 69239df32..363994919 100644
--- a/dev/sinic.cc
+++ b/dev/sinic.cc
@@ -47,9 +47,10 @@
#include "sim/eventq.hh"
#include "sim/host.hh"
#include "sim/stats.hh"
-#include "targetarch/vtophys.hh"
+#include "arch/vtophys.hh"
using namespace Net;
+using namespace TheISA;
namespace Sinic {
@@ -112,8 +113,6 @@ Device::Device(Params *p)
p->dma_no_allocate);
} else if (p->payload_bus)
panic("must define a header bus if defining a payload bus");
-
- pioDelayWrite = p->pio_delay_write && pioInterface;
}
Device::~Device()
@@ -352,9 +351,6 @@ Device::prepareRead(int cpu, int index)
void
Device::prepareWrite(int cpu, int index)
{
- if (cpu >= writeQueue.size())
- writeQueue.resize(cpu + 1);
-
prepareIO(cpu, index);
}
@@ -367,11 +363,11 @@ Device::read(MemReqPtr &req, uint8_t *data)
assert(config.command & PCI_CMD_MSE);
Fault fault = readBar(req, data);
- if (fault == Machine_Check_Fault) {
+ if (fault->isMachineCheckFault()) {
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 genMachineCheckFault();
}
return fault;
@@ -380,7 +376,7 @@ Device::read(MemReqPtr &req, uint8_t *data)
Fault
Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
{
- int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff;
Addr index = daddr >> Regs::VirtualShift;
Addr raddr = daddr & Regs::VirtualMask;
@@ -421,7 +417,7 @@ Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
if (raddr == Regs::IntrStatus)
devIntrClear();
- return No_Fault;
+ return NoFault;
}
/**
@@ -451,7 +447,7 @@ Device::iprRead(Addr daddr, int cpu, uint64_t &result)
DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",
info.name, cpu, result);
- return No_Fault;
+ return NoFault;
}
/**
@@ -463,11 +459,11 @@ Device::write(MemReqPtr &req, const uint8_t *data)
assert(config.command & PCI_CMD_MSE);
Fault fault = writeBar(req, data);
- if (fault == Machine_Check_Fault) {
+ if (fault->isMachineCheckFault()) {
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 genMachineCheckFault();
}
return fault;
@@ -476,7 +472,7 @@ Device::write(MemReqPtr &req, const uint8_t *data)
Fault
Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
{
- int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff;
Addr index = daddr >> Regs::VirtualShift;
Addr raddr = daddr & Regs::VirtualMask;
@@ -495,32 +491,15 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
uint32_t reg32 = *(uint32_t *)data;
uint64_t reg64 = *(uint64_t *)data;
+ VirtualReg &vnic = virtualRegs[index];
+
DPRINTF(EthernetPIO,
"write %s: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n",
- info.name, cpu, info.size == 4 ? reg32 : reg64, daddr,
- req->paddr, req->vaddr, req->size);
+ info.name, cpu, info.size == 4 ? reg32 : reg64,
+ daddr, req->paddr, req->vaddr, req->size);
prepareWrite(cpu, index);
- if (pioDelayWrite)
- writeQueue[cpu].push_back(RegWriteData(daddr, reg64));
-
- if (!pioDelayWrite || !info.delay_write)
- regWrite(daddr, cpu, data);
-
- return No_Fault;
-}
-
-void
-Device::regWrite(Addr daddr, int cpu, const uint8_t *data)
-{
- Addr index = daddr >> Regs::VirtualShift;
- Addr raddr = daddr & Regs::VirtualMask;
-
- uint32_t reg32 = *(uint32_t *)data;
- uint64_t reg64 = *(uint64_t *)data;
- VirtualReg &vnic = virtualRegs[index];
-
switch (raddr) {
case Regs::Config:
changeConfig(reg32);
@@ -567,6 +546,8 @@ Device::regWrite(Addr daddr, int cpu, const uint8_t *data)
}
break;
}
+
+ return NoFault;
}
void
@@ -780,6 +761,8 @@ Device::reset()
regs.Config |= Config_RxThread;
if (params()->tx_thread)
regs.Config |= Config_TxThread;
+ if (params()->rss)
+ regs.Config |= Config_RSS;
regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
regs.RxMaxCopy = params()->rx_max_copy;
regs.TxMaxCopy = params()->tx_max_copy;
@@ -1570,27 +1553,6 @@ Device::cacheAccess(MemReqPtr &req)
DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n",
req->cmd.toString(), req->paddr, bar, daddr);
- if (!pioDelayWrite || !req->cmd.isWrite())
- return curTick + pioLatency;
-
- if (bar == 0) {
- int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
- std::list<RegWriteData> &wq = writeQueue[cpu];
- if (wq.empty())
- panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr);
-
- const RegWriteData &data = wq.front();
- if (data.daddr != daddr)
- panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
- cpu, data.daddr, daddr);
-
- const Regs::Info &info = regInfo(data.daddr);
- if (info.delay_write)
- regWrite(daddr, cpu, (uint8_t *)&data.value);
-
- wq.pop_front();
- }
-
return curTick + pioLatency;
}
@@ -1648,7 +1610,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
Param<Tick> dma_write_factor;
Param<bool> dma_no_allocate;
Param<Tick> pio_latency;
- Param<bool> pio_delay_write;
Param<Tick> intr_delay;
Param<Tick> rx_delay;
@@ -1665,6 +1626,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
Param<string> hardware_address;
Param<bool> rx_thread;
Param<bool> tx_thread;
+ Param<bool> rss;
END_DECLARE_SIM_OBJECT_PARAMS(Device)
@@ -1692,7 +1654,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"),
INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"),
- INIT_PARAM(pio_delay_write, ""),
INIT_PARAM(intr_delay, "Interrupt Delay"),
INIT_PARAM(rx_delay, "Receive Delay"),
@@ -1708,7 +1669,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(rx_filter, "Enable Receive Filter"),
INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
INIT_PARAM(rx_thread, ""),
- INIT_PARAM(tx_thread, "")
+ INIT_PARAM(tx_thread, ""),
+ INIT_PARAM(rss, "")
END_INIT_SIM_OBJECT_PARAMS(Device)
@@ -1740,7 +1702,6 @@ CREATE_SIM_OBJECT(Device)
params->dma_write_factor = dma_write_factor;
params->dma_no_allocate = dma_no_allocate;
params->pio_latency = pio_latency;
- params->pio_delay_write = pio_delay_write;
params->intr_delay = intr_delay;
params->tx_delay = tx_delay;
@@ -1757,6 +1718,7 @@ CREATE_SIM_OBJECT(Device)
params->eaddr = hardware_address;
params->rx_thread = rx_thread;
params->tx_thread = tx_thread;
+ params->rss = rss;
return new Device(params);
}
diff --git a/dev/sinic.hh b/dev/sinic.hh
index af2f109a4..25172fa45 100644
--- a/dev/sinic.hh
+++ b/dev/sinic.hh
@@ -280,20 +280,8 @@ class Device : public Base
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);
- protected:
- struct RegWriteData {
- Addr daddr;
- uint64_t value;
- RegWriteData(Addr da, uint64_t val) : daddr(da), value(val) {}
- };
-
- std::vector<std::list<RegWriteData> > writeQueue;
-
- bool pioDelayWrite;
-
/**
* Statistics
*/
@@ -349,7 +337,6 @@ class Device : public Base
Bus *header_bus;
Bus *payload_bus;
Tick pio_latency;
- bool pio_delay_write;
PhysicalMemory *physmem;
IntrControl *intctrl;
bool rx_filter;
@@ -368,6 +355,7 @@ class Device : public Base
bool dma_no_allocate;
bool rx_thread;
bool tx_thread;
+ bool rss;
};
protected:
diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh
index b7008b4e1..f90432398 100644
--- a/dev/sinicreg.hh
+++ b/dev/sinicreg.hh
@@ -81,6 +81,7 @@ __SINIC_REG32(HwAddr, 0x60); // 64: mac address
__SINIC_REG32(Size, 0x68); // register addres space size
// Config register bits
+__SINIC_VAL32(Config_RSS, 10, 1); // enable receive side scaling
__SINIC_VAL32(Config_RxThread, 9, 1); // enable receive threads
__SINIC_VAL32(Config_TxThread, 8, 1); // enable transmit thread
__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter
@@ -157,8 +158,6 @@ struct Info
uint8_t size;
bool read;
bool write;
- bool delay_read;
- bool delay_write;
const char *name;
};
@@ -167,33 +166,33 @@ struct Info
inline const Regs::Info&
regInfo(Addr daddr)
{
- static Regs::Info invalid = { 0, false, false, false, false, "invalid" };
+ static Regs::Info invalid = { 0, false, false, "invalid" };
static Regs::Info info [] = {
- { 4, true, true, false, false, "Config" },
- { 4, false, true, false, false, "Command" },
- { 4, true, true, false, false, "IntrStatus" },
- { 4, true, true, false, false, "IntrMask" },
- { 4, true, false, false, false, "RxMaxCopy" },
- { 4, true, false, false, false, "TxMaxCopy" },
- { 4, true, false, false, false, "RxMaxIntr" },
+ { 4, true, true, "Config" },
+ { 4, false, true, "Command" },
+ { 4, true, true, "IntrStatus" },
+ { 4, true, true, "IntrMask" },
+ { 4, true, false, "RxMaxCopy" },
+ { 4, true, false, "TxMaxCopy" },
+ { 4, true, false, "RxMaxIntr" },
invalid,
- { 4, true, false, false, false, "RxFifoSize" },
- { 4, true, false, false, false, "TxFifoSize" },
- { 4, true, false, false, false, "RxFifoMark" },
- { 4, true, false, false, false, "TxFifoMark" },
- { 8, true, true, false, true, "RxData" },
+ { 4, true, false, "RxFifoSize" },
+ { 4, true, false, "TxFifoSize" },
+ { 4, true, false, "RxFifoMark" },
+ { 4, true, false, "TxFifoMark" },
+ { 8, true, true, "RxData" },
invalid,
- { 8, true, false, false, false, "RxDone" },
+ { 8, true, false, "RxDone" },
invalid,
- { 8, true, false, false, false, "RxWait" },
+ { 8, true, false, "RxWait" },
invalid,
- { 8, true, true, false, true, "TxData" },
+ { 8, true, true, "TxData" },
invalid,
- { 8, true, false, false, false, "TxDone" },
+ { 8, true, false, "TxDone" },
invalid,
- { 8, true, false, false, false, "TxWait" },
+ { 8, true, false, "TxWait" },
invalid,
- { 8, true, false, false, false, "HwAddr" },
+ { 8, true, false, "HwAddr" },
invalid,
};
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index 760848a00..58fc7434e 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -46,6 +46,8 @@
#include "sim/system.hh"
using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
Tsunami::Tsunami(const string &name, System *s, IntrControl *ic,
PciConfigAll *pci)
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index 2287a2a3d..2649fe27a 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -42,11 +42,14 @@
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional/memory_control.hh"
+#include "cpu/exec_context.hh"
#include "cpu/intr_control.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
MemoryController *mmu, HierParams *hier,
@@ -92,81 +95,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;
+ (xc->readCpuId() & 0x3);
+ 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 +182,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
*(uint32_t*)data = drir;
} else
panic("invalid access size(?) for tsunami register!\n");
- return No_Fault;
+ return NoFault;
case sizeof(uint16_t):
case sizeof(uint8_t):
default:
@@ -187,7 +190,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
}
DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size);
- return No_Fault;
+ return NoFault;
}
Fault
@@ -243,16 +246,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 +288,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 +344,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 +366,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 +387,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 724a5bfb9..e66d6653b 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -50,6 +50,8 @@
#include "mem/functional/memory_control.hh"
using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i)
: _name(name), event(t, i), addr(0)
@@ -459,38 +461,38 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
// PIC1 mask read
case TSDEV_PIC1_MASK:
*(uint8_t*)data = ~mask1;
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_MASK:
*(uint8_t*)data = ~mask2;
- return No_Fault;
+ return NoFault;
case TSDEV_PIC1_ISR:
// !!! If this is modified 64bit case needs to be too
// Pal code has to do a 64 bit physical read because there is
// no load physical byte instruction
*(uint8_t*)data = picr;
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_ISR:
// PIC2 not implemnted... just return 0
*(uint8_t*)data = 0x00;
- return No_Fault;
+ return NoFault;
case TSDEV_TMR0_DATA:
pitimer.counter0.read(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR1_DATA:
pitimer.counter1.read(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR2_DATA:
pitimer.counter2.read(data);
- return No_Fault;
+ return NoFault;
case TSDEV_RTC_DATA:
rtc.readData(data);
- return No_Fault;
+ return NoFault;
case TSDEV_CTRL_PORTB:
if (pitimer.counter2.outputHigh())
*data = PORTB_SPKR_HIGH;
else
*data = 0x00;
- return No_Fault;
+ return NoFault;
default:
panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
}
@@ -506,7 +508,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
// Pal code has to do a 64 bit physical read because there is
// no load physical byte instruction
*(uint64_t*)data = (uint64_t)picr;
- return No_Fault;
+ return NoFault;
default:
panic("I/O Read - invalid size - va %#x size %d\n",
req->vaddr, req->size);
@@ -518,7 +520,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
}
panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
- return No_Fault;
+ return NoFault;
}
Fault
@@ -550,63 +552,63 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
tsunami->cchip->clearDRIR(55);
DPRINTF(Tsunami, "clearing pic interrupt\n");
}
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_MASK:
mask2 = *(uint8_t*)data;
//PIC2 Not implemented to interrupt
- return No_Fault;
+ return NoFault;
case TSDEV_PIC1_ACK:
// clear the interrupt on the PIC
picr &= ~(1 << (*(uint8_t*)data & 0xF));
if (!(picr & mask1))
tsunami->cchip->clearDRIR(55);
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_CMND:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_CMND:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_MMASK:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_MMASK:
- return No_Fault;
+ return NoFault;
case TSDEV_PIC2_ACK:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_RESET:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_RESET:
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_MODE:
mode1 = *(uint8_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_DMA2_MODE:
mode2 = *(uint8_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_DMA1_MASK:
case TSDEV_DMA2_MASK:
- return No_Fault;
+ return NoFault;
case TSDEV_TMR0_DATA:
pitimer.counter0.write(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR1_DATA:
pitimer.counter1.write(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR2_DATA:
pitimer.counter2.write(data);
- return No_Fault;
+ return NoFault;
case TSDEV_TMR_CTRL:
pitimer.writeControl(data);
- return No_Fault;
+ return NoFault;
case TSDEV_RTC_ADDR:
rtc.writeAddr(data);
- return No_Fault;
+ return NoFault;
case TSDEV_KBD:
- return No_Fault;
+ return NoFault;
case TSDEV_RTC_DATA:
rtc.writeData(data);
- return No_Fault;
+ return NoFault;
case TSDEV_CTRL_PORTB:
// System Control Port B not implemented
- return No_Fault;
+ return NoFault;
default:
panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data);
}
@@ -619,7 +621,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
}
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index e61137170..46efc3dfe 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -47,6 +47,8 @@
#include "sim/system.hh"
using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
MemoryController *mmu, HierParams *hier,
@@ -90,60 +92,60 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
switch(daddr) {
case TSDEV_PC_WSBA0:
*(uint64_t*)data = wsba[0];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA1:
*(uint64_t*)data = wsba[1];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA2:
*(uint64_t*)data = wsba[2];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA3:
*(uint64_t*)data = wsba[3];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM0:
*(uint64_t*)data = wsm[0];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM1:
*(uint64_t*)data = wsm[1];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM2:
*(uint64_t*)data = wsm[2];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM3:
*(uint64_t*)data = wsm[3];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA0:
*(uint64_t*)data = tba[0];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA1:
*(uint64_t*)data = tba[1];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA2:
*(uint64_t*)data = tba[2];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA3:
*(uint64_t*)data = tba[3];
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PCTL:
*(uint64_t*)data = pctl;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PLAT:
panic("PC_PLAT not implemented\n");
case TSDEV_PC_RES:
panic("PC_RES not implemented\n");
case TSDEV_PC_PERROR:
*(uint64_t*)data = 0x00;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PERRMASK:
*(uint64_t*)data = 0x00;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PERRSET:
panic("PC_PERRSET not implemented\n");
case TSDEV_PC_TLBIV:
panic("PC_TLBIV not implemented\n");
case TSDEV_PC_TLBIA:
*(uint64_t*)data = 0x00; // shouldn't be readable, but linux
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PMONCTL:
panic("PC_PMONCTL not implemented\n");
case TSDEV_PC_PMONCNT:
@@ -162,7 +164,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
}
DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
Fault
@@ -179,49 +181,49 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
switch(daddr) {
case TSDEV_PC_WSBA0:
wsba[0] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA1:
wsba[1] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA2:
wsba[2] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSBA3:
wsba[3] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM0:
wsm[0] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM1:
wsm[1] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM2:
wsm[2] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_WSM3:
wsm[3] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA0:
tba[0] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA1:
tba[1] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA2:
tba[2] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_TBA3:
tba[3] = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PCTL:
pctl = *(uint64_t*)data;
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PLAT:
panic("PC_PLAT not implemented\n");
case TSDEV_PC_RES:
panic("PC_RES not implemented\n");
case TSDEV_PC_PERROR:
- return No_Fault;
+ return NoFault;
case TSDEV_PC_PERRMASK:
panic("PC_PERRMASK not implemented\n");
case TSDEV_PC_PERRSET:
@@ -229,7 +231,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_PC_TLBIV:
panic("PC_TLBIV not implemented\n");
case TSDEV_PC_TLBIA:
- return No_Fault; // value ignored, supposted to invalidate SG TLB
+ return NoFault; // value ignored, supposted to invalidate SG TLB
case TSDEV_PC_PMONCTL:
panic("PC_PMONCTL not implemented\n");
case TSDEV_PC_PMONCNT:
@@ -249,7 +251,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
- return No_Fault;
+ return NoFault;
}
#define DMA_ADDR_MASK ULL(0x3ffffffff)
diff --git a/dev/uart.hh b/dev/uart.hh
index 145b9ca9e..78b1dc68e 100644
--- a/dev/uart.hh
+++ b/dev/uart.hh
@@ -37,6 +37,7 @@
#include "dev/io_device.hh"
class SimConsole;
+class MemoryController;
class Platform;
const int RX_INT = 0x1;
diff --git a/dev/uart8250.cc b/dev/uart8250.cc
index 71f429069..65bccee86 100644
--- a/dev/uart8250.cc
+++ b/dev/uart8250.cc
@@ -46,6 +46,7 @@
#include "sim/builder.hh"
using namespace std;
+using namespace TheISA;
Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit)
: Event(&mainEventQueue), uart(u)
@@ -183,7 +184,7 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
break;
}
- return No_Fault;
+ return NoFault;
}
@@ -255,7 +256,7 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data)
panic("Tried to access a UART port that doesn't exist\n");
break;
}
- return No_Fault;
+ return NoFault;
}
void
diff --git a/dev/uart8250.hh b/dev/uart8250.hh
index 88abf8e24..63d1da3cf 100644
--- a/dev/uart8250.hh
+++ b/dev/uart8250.hh
@@ -53,6 +53,7 @@
#define IIR_LINE 0x06 /* Rx Line Status (highest priority)*/
class SimConsole;
+class MemoryController;
class Platform;
class Uart8250 : public Uart
diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc
index 3a7d12443..b85d88145 100644
--- a/kern/kernel_stats.cc
+++ b/kern/kernel_stats.cc
@@ -35,6 +35,7 @@
#include "cpu/exec_context.hh"
#include "kern/kernel_stats.hh"
#include "kern/tru64/tru64_syscalls.hh"
+#include "sim/system.hh"
using namespace std;
using namespace Stats;
@@ -43,11 +44,11 @@ namespace Kernel {
const char *modestr[] = { "kernel", "user", "idle", "interrupt" };
-Statistics::Statistics(ExecContext *context)
- : xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
+Statistics::Statistics(System *system)
+ : idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
iplLast(0), iplLastTick(0)
{
- bin_int = xc->system->params->bin_int;
+ bin_int = system->params()->bin_int;
}
void
@@ -136,19 +137,6 @@ Statistics::regStats(const string &_name)
}
}
- _faults
- .init(Num_Faults)
- .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);
- if (str)
- _faults.subname(i, str);
- }
-
_mode
.init(cpu_mode_num)
.name(name() + ".mode_switch")
@@ -193,16 +181,16 @@ Statistics::regStats(const string &_name)
}
void
-Statistics::setIdleProcess(Addr idlepcbb)
+Statistics::setIdleProcess(Addr idlepcbb, ExecContext *xc)
{
assert(themode == kernel || themode == interrupt);
idleProcess = idlepcbb;
themode = idle;
- changeMode(themode);
+ changeMode(themode, xc);
}
void
-Statistics::changeMode(cpu_mode newmode)
+Statistics::changeMode(cpu_mode newmode, ExecContext *xc)
{
_mode[newmode]++;
@@ -215,7 +203,7 @@ Statistics::changeMode(cpu_mode newmode)
_modeGood[newmode]++;
_modeTicks[themode] += curTick - lastModeTick;
- xc->system->kernelBinning->changeMode(newmode);
+ xc->getSystemPtr()->kernelBinning->changeMode(newmode);
lastModeTick = curTick;
themode = newmode;
@@ -238,9 +226,9 @@ Statistics::swpipl(int ipl)
}
void
-Statistics::mode(cpu_mode newmode)
+Statistics::mode(cpu_mode newmode, ExecContext *xc)
{
- Addr pcbb = xc->regs.ipr[AlphaISA::IPR_PALtemp23];
+ Addr pcbb = xc->readMiscReg(AlphaISA::IPR_PALtemp23);
if ((newmode == kernel || newmode == interrupt) &&
pcbb == idleProcess)
@@ -249,20 +237,20 @@ Statistics::mode(cpu_mode newmode)
if (bin_int == false && newmode == interrupt)
newmode = kernel;
- changeMode(newmode);
+ changeMode(newmode, xc);
}
void
-Statistics::context(Addr oldpcbb, Addr newpcbb)
+Statistics::context(Addr oldpcbb, Addr newpcbb, ExecContext *xc)
{
assert(themode != user);
_swap_context++;
- changeMode(newpcbb == idleProcess ? idle : kernel);
+ changeMode(newpcbb == idleProcess ? idle : kernel, xc);
}
void
-Statistics::callpal(int code)
+Statistics::callpal(int code, ExecContext *xc)
{
if (!PAL::name(code))
return;
@@ -271,7 +259,7 @@ Statistics::callpal(int code)
switch (code) {
case PAL::callsys: {
- int number = xc->regs.intRegFile[0];
+ int number = xc->readIntReg(0);
if (SystemCalls<Tru64>::validSyscallNumber(number)) {
int cvtnum = SystemCalls<Tru64>::convert(number);
_syscall[cvtnum]++;
@@ -279,8 +267,8 @@ Statistics::callpal(int code)
} break;
case PAL::swpctx:
- if (xc->system->kernelBinning)
- xc->system->kernelBinning->palSwapContext(xc);
+ if (xc->getSystemPtr()->kernelBinning)
+ xc->getSystemPtr()->kernelBinning->palSwapContext(xc);
break;
}
}
diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh
index 62dd84a28..16ec721d0 100644
--- a/kern/kernel_stats.hh
+++ b/kern/kernel_stats.hh
@@ -41,7 +41,6 @@ class ExecContext;
class FnEvent;
// What does kernel stats expect is included?
class System;
-enum Fault;
namespace Kernel {
@@ -106,7 +105,7 @@ class Binning
cpu_mode themode;
void palSwapContext(ExecContext *xc);
- void execute(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ void execute(ExecContext *xc, StaticInstPtr inst);
void call(ExecContext *xc, Stats::MainBin *myBin);
void changeMode(cpu_mode mode);
@@ -124,18 +123,18 @@ class Binning
class Statistics : public Serializable
{
+ private:
friend class Binning;
private:
std::string myname;
- ExecContext *xc;
Addr idleProcess;
cpu_mode themode;
Tick lastModeTick;
bool bin_int;
- void changeMode(cpu_mode newmode);
+ void changeMode(cpu_mode newmode, ExecContext *xc);
private:
Stats::Scalar<> _arm;
@@ -151,7 +150,7 @@ class Statistics : public Serializable
Stats::Vector<> _callpal;
Stats::Vector<> _syscall;
- Stats::Vector<> _faults;
+// Stats::Vector<> _faults;
Stats::Vector<> _mode;
Stats::Vector<> _modeGood;
@@ -165,7 +164,7 @@ class Statistics : public Serializable
Tick iplLastTick;
public:
- Statistics(ExecContext *context);
+ Statistics(System *system);
const std::string name() const { return myname; }
void regStats(const std::string &name);
@@ -176,13 +175,12 @@ class Statistics : public Serializable
void ivlb() { _ivlb++; }
void ivle() { _ivle++; }
void hwrei() { _hwrei++; }
- void fault(Fault fault) { _faults[fault]++; }
void swpipl(int ipl);
- void mode(cpu_mode newmode);
- void context(Addr oldpcbb, Addr newpcbb);
- void callpal(int code);
+ void mode(cpu_mode newmode, ExecContext *xc);
+ void context(Addr oldpcbb, Addr newpcbb, ExecContext *xc);
+ void callpal(int code, ExecContext *xc);
- void setIdleProcess(Addr idle);
+ void setIdleProcess(Addr idle, ExecContext *xc);
public:
virtual void serialize(std::ostream &os);
diff --git a/kern/linux/events.cc b/kern/linux/events.cc
new file mode 100644
index 000000000..9f50eef04
--- /dev/null
+++ b/kern/linux/events.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/arguments.hh"
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/events.hh"
+#include "kern/linux/printk.hh"
+#include "kern/system_events.hh"
+#include "sim/system.hh"
+
+
+namespace Linux {
+
+void
+DebugPrintkEvent::process(ExecContext *xc)
+{
+ if (DTRACE(DebugPrintf)) {
+ if (!raw) {
+ StringWrap name(xc->getSystemPtr()->name() + ".dprintk");
+ DPRINTFN("");
+ }
+
+ AlphaArguments args(xc);
+ Printk(args);
+ SkipFuncEvent::process(xc);
+ }
+}
+
+} // namespace linux
diff --git a/kern/linux/events.hh b/kern/linux/events.hh
new file mode 100644
index 000000000..95c268976
--- /dev/null
+++ b/kern/linux/events.hh
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __KERN_LINUX_EVENTS_HH__
+#define __KERN_LINUX_EVENTS_HH__
+
+#include "kern/system_events.hh"
+
+namespace Linux {
+
+class DebugPrintkEvent : public SkipFuncEvent
+{
+ private:
+ bool raw;
+
+ public:
+ DebugPrintkEvent(PCEventQueue *q, const std::string &desc, Addr addr,
+ bool r = false)
+ : SkipFuncEvent(q, desc, addr), raw(r) {}
+ virtual void process(ExecContext *xc);
+};
+
+}
+
+#endif
diff --git a/kern/linux/linux.hh b/kern/linux/linux.hh
index b083b5a31..0dbccf546 100644
--- a/kern/linux/linux.hh
+++ b/kern/linux/linux.hh
@@ -28,7 +28,314 @@
#ifndef __LINUX_HH__
#define __LINUX_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
class Linux {};
+#else //!FULL_SYSTEM
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h> // for host open() flags
+#include <string.h> // for memset()
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sim/syscall_emul.hh"
+
+///
+/// This class encapsulates the types, structures, constants,
+/// functions, and syscall-number mappings specific to the Alpha Linux
+/// syscall interface.
+///
+class Linux {
+
+ public:
+
+ //@{
+ /// Basic Linux types.
+ typedef uint64_t size_t;
+ typedef uint64_t off_t;
+ typedef int64_t time_t;
+ typedef uint32_t uid_t;
+ typedef uint32_t gid_t;
+ //@}
+
+#if BSD_HOST
+ typedef struct stat hst_stat;
+ typedef struct stat hst_stat64;
+#else
+ typedef struct stat hst_stat ;
+ typedef struct stat64 hst_stat64;
+#endif
+
+
+ //@{
+ /// open(2) flag values.
+ static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
+ static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
+ static const int TGT_O_RDWR = 00000002; //!< O_RDWR
+ static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK
+ static const int TGT_O_APPEND = 00000010; //!< O_APPEND
+ static const int TGT_O_CREAT = 00001000; //!< O_CREAT
+ static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC
+ static const int TGT_O_EXCL = 00004000; //!< O_EXCL
+ static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY
+ static const int TGT_O_SYNC = 00040000; //!< O_SYNC
+ static const int TGT_O_DRD = 00100000; //!< O_DRD
+ static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO
+ static const int TGT_O_CACHE = 00400000; //!< O_CACHE
+ static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC
+ static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC
+ //@}
+
+ /// This table maps the target open() flags to the corresponding
+ /// host open() flags.
+ static OpenFlagTransTable openFlagTable[];
+
+ /// Number of entries in openFlagTable[].
+ static const int NUM_OPEN_FLAGS;
+
+ /// Stat buffer. Note that we can't call it 'stat' since that
+ /// gets #defined to something else on some systems.
+ struct tgt_stat {
+ uint32_t st_dev; //!< device
+ uint32_t st_ino; //!< inode
+ uint32_t st_mode; //!< mode
+ uint32_t st_nlink; //!< link count
+ uint32_t st_uid; //!< owner's user ID
+ uint32_t st_gid; //!< owner's group ID
+ uint32_t st_rdev; //!< device number
+ int32_t _pad1; //!< for alignment
+ int64_t st_size; //!< file size in bytes
+ uint64_t st_atimeX; //!< time of last access
+ uint64_t st_mtimeX; //!< time of last modification
+ uint64_t st_ctimeX; //!< time of last status change
+ uint32_t st_blksize; //!< optimal I/O block size
+ int32_t st_blocks; //!< number of blocks allocated
+ uint32_t st_flags; //!< flags
+ uint32_t st_gen; //!< unknown
+ };
+
+ // same for stat64
+ struct tgt_stat64 {
+ uint64_t st_dev;
+ uint64_t st_ino;
+ uint64_t st_rdev;
+ int64_t st_size;
+ uint64_t st_blocks;
+
+ uint32_t st_mode;
+ uint32_t st_uid;
+ uint32_t st_gid;
+ uint32_t st_blksize;
+ uint32_t st_nlink;
+ uint32_t __pad0;
+
+ uint64_t tgt_st_atime;
+ uint64_t st_atime_nsec;
+ uint64_t tgt_st_mtime;
+ uint64_t st_mtime_nsec;
+ uint64_t tgt_st_ctime;
+ uint64_t st_ctime_nsec;
+ int64_t ___unused[3];
+ };
+
+ /// Length of strings in struct utsname (plus 1 for null char).
+ static const int _SYS_NMLN = 65;
+
+ /// Interface struct for uname().
+ struct utsname {
+ char sysname[_SYS_NMLN]; //!< System name.
+ char nodename[_SYS_NMLN]; //!< Node name.
+ char release[_SYS_NMLN]; //!< OS release.
+ char version[_SYS_NMLN]; //!< OS version.
+ char machine[_SYS_NMLN]; //!< Machine type.
+ };
+
+
+ //@{
+ /// ioctl() command codes.
+ static const unsigned TIOCGETP = 0x40067408;
+ static const unsigned TIOCSETP = 0x80067409;
+ static const unsigned TIOCSETN = 0x8006740a;
+ static const unsigned TIOCSETC = 0x80067411;
+ static const unsigned TIOCGETC = 0x40067412;
+ static const unsigned FIONREAD = 0x4004667f;
+ static const unsigned TIOCISATTY = 0x2000745e;
+ static const unsigned TIOCGETS = 0x402c7413;
+ static const unsigned TIOCGETA = 0x40127417;
+ //@}
+
+ /// Resource enumeration for getrlimit().
+ enum rlimit_resources {
+ TGT_RLIMIT_CPU = 0,
+ TGT_RLIMIT_FSIZE = 1,
+ TGT_RLIMIT_DATA = 2,
+ TGT_RLIMIT_STACK = 3,
+ TGT_RLIMIT_CORE = 4,
+ TGT_RLIMIT_RSS = 5,
+ TGT_RLIMIT_NOFILE = 6,
+ TGT_RLIMIT_AS = 7,
+ TGT_RLIMIT_VMEM = 7,
+ TGT_RLIMIT_NPROC = 8,
+ TGT_RLIMIT_MEMLOCK = 9,
+ TGT_RLIMIT_LOCKS = 10
+ };
+
+ /// Limit struct for getrlimit/setrlimit.
+ struct rlimit {
+ uint64_t rlim_cur; //!< soft limit
+ uint64_t rlim_max; //!< hard limit
+ };
+
+
+ /// For mmap().
+ static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+
+ /// For gettimeofday().
+ struct timeval {
+ int64_t tv_sec; //!< seconds
+ int64_t tv_usec; //!< microseconds
+ };
+
+ // For writev/readv
+ struct tgt_iovec {
+ uint64_t iov_base; // void *
+ uint64_t iov_len;
+ };
+
+ //@{
+ /// For getrusage().
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
+ static const int TGT_RUSAGE_BOTH = -2;
+ //@}
+
+ /// For getrusage().
+ struct rusage {
+ struct timeval ru_utime; //!< user time used
+ struct timeval ru_stime; //!< system time used
+ int64_t ru_maxrss; //!< max rss
+ int64_t ru_ixrss; //!< integral shared memory size
+ int64_t ru_idrss; //!< integral unshared data "
+ int64_t ru_isrss; //!< integral unshared stack "
+ int64_t ru_minflt; //!< page reclaims - total vmfaults
+ int64_t ru_majflt; //!< page faults
+ int64_t ru_nswap; //!< swaps
+ int64_t ru_inblock; //!< block input operations
+ int64_t ru_oublock; //!< block output operations
+ int64_t ru_msgsnd; //!< messages sent
+ int64_t ru_msgrcv; //!< messages received
+ int64_t ru_nsignals; //!< signals received
+ int64_t ru_nvcsw; //!< voluntary context switches
+ int64_t ru_nivcsw; //!< involuntary "
+ };
+
+ /// Helper function to convert a host stat buffer to a target stat
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by stat(), fstat(), and lstat().
+#if !BSD_HOST
+ static void
+ copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
+ {
+ TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+#else
+ // Third version for bsd systems which no longer have any support for
+ // the old stat() call and stat() is actually a stat64()
+ static void
+ copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host)
+ {
+ TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+#endif
+
+
+ // Same for stat64
+ static void
+ copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host)
+ {
+ TypedBufferArg<Linux::tgt_stat64> tgt(addr);
+
+ // fd == 1 checks are because libc does some checks
+ // that the stdout is interactive vs. a file
+ // this makes it work on non-linux systems
+ if (fd == 1)
+ tgt->st_dev = htog((uint64_t)0xA);
+ else
+ tgt->st_dev = htog((uint64_t)host->st_dev);
+ // XXX What about STAT64_HAS_BROKEN_ST_INO ???
+ tgt->st_ino = htog((uint64_t)host->st_ino);
+ if (fd == 1)
+ tgt->st_rdev = htog((uint64_t)0x880d);
+ else
+ tgt->st_rdev = htog((uint64_t)host->st_rdev);
+ tgt->st_size = htog((int64_t)host->st_size);
+ tgt->st_blocks = htog((uint64_t)host->st_blocks);
+
+ if (fd == 1)
+ tgt->st_mode = htog((uint32_t)0x2190);
+ else
+ tgt->st_mode = htog((uint32_t)host->st_mode);
+ tgt->st_uid = htog((uint32_t)host->st_uid);
+ tgt->st_gid = htog((uint32_t)host->st_gid);
+ tgt->st_blksize = htog((uint32_t)host->st_blksize);
+ tgt->st_nlink = htog((uint32_t)host->st_nlink);
+ tgt->tgt_st_atime = htog((uint64_t)host->st_atime);
+ tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime);
+ tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime);
+#if defined(STAT_HAVE_NSEC)
+ tgt->st_atime_nsec = htog(host->st_atime_nsec);
+ tgt->st_mtime_nsec = htog(host->st_mtime_nsec);
+ tgt->st_ctime_nsec = htog(host->st_ctime_nsec);
+#else
+ tgt->st_atime_nsec = 0;
+ tgt->st_mtime_nsec = 0;
+ tgt->st_ctime_nsec = 0;
+#endif
+
+ tgt.copyOut(mem);
+ }
+
+}; // class Linux
+
+
+#endif // FULL_SYSTEM
+
#endif // __LINUX_HH__
diff --git a/kern/linux/printk.cc b/kern/linux/printk.cc
index fbc8bdad1..f5313759b 100644
--- a/kern/linux/printk.cc
+++ b/kern/linux/printk.cc
@@ -30,7 +30,7 @@
#include <algorithm>
#include "base/trace.hh"
-#include "targetarch/arguments.hh"
+#include "arch/arguments.hh"
using namespace std;
diff --git a/kern/system_events.cc b/kern/system_events.cc
index ba3c9274a..9b9861497 100644
--- a/kern/system_events.cc
+++ b/kern/system_events.cc
@@ -29,20 +29,22 @@
#include "encumbered/cpu/full/cpu.hh"
#include "kern/kernel_stats.hh"
+using namespace TheISA;
+
void
SkipFuncEvent::process(ExecContext *xc)
{
- Addr newpc = xc->regs.intRegFile[ReturnAddressReg];
+ Addr newpc = xc->readIntReg(ReturnAddressReg);
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
- xc->regs.pc, newpc);
+ xc->readPC(), newpc);
- xc->regs.pc = newpc;
- xc->regs.npc = xc->regs.pc + sizeof(MachInst);
+ xc->setPC(newpc);
+ xc->setNextPC(xc->readPC() + sizeof(TheISA::MachInst));
- BranchPred *bp = xc->cpu->getBranchPred();
+ BranchPred *bp = xc->getCpuPtr()->getBranchPred();
if (bp != NULL) {
- bp->popRAS(xc->thread_num);
+ bp->popRAS(xc->getThreadNum());
}
}
@@ -59,20 +61,21 @@ FnEvent::process(ExecContext *xc)
if (xc->misspeculating())
return;
- xc->system->kernelBinning->call(xc, mybin);
+ xc->getSystemPtr()->kernelBinning->call(xc, mybin);
}
void
IdleStartEvent::process(ExecContext *xc)
{
- xc->kernelStats->setIdleProcess(xc->regs.ipr[AlphaISA::IPR_PALtemp23]);
+ xc->getCpuPtr()->kernelStats->setIdleProcess(
+ xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc);
remove();
}
void
InterruptStartEvent::process(ExecContext *xc)
{
- xc->kernelStats->mode(Kernel::interrupt);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::interrupt, xc);
}
void
@@ -80,5 +83,5 @@ InterruptEndEvent::process(ExecContext *xc)
{
// We go back to kernel, if we are user, inside the rti
// pal code we will get switched to user because of the ICM write
- xc->kernelStats->mode(Kernel::kernel);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc);
}
diff --git a/kern/tru64/dump_mbuf.cc b/kern/tru64/dump_mbuf.cc
index 215930923..c3c37531a 100644
--- a/kern/tru64/dump_mbuf.cc
+++ b/kern/tru64/dump_mbuf.cc
@@ -31,12 +31,16 @@
#include "base/cprintf.hh"
#include "base/trace.hh"
+#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh"
#include "kern/tru64/mbuf.hh"
#include "sim/host.hh"
-#include "targetarch/arguments.hh"
-#include "targetarch/isa_traits.hh"
-#include "targetarch/vtophys.hh"
+#include "sim/system.hh"
+#include "arch/arguments.hh"
+#include "arch/isa_traits.hh"
+#include "arch/vtophys.hh"
+
+using namespace TheISA;
namespace tru64 {
@@ -59,7 +63,7 @@ DumpMbuf(AlphaArguments args)
addr, m.m_data, m.m_len);
char *buffer = new char[m.m_len];
CopyOut(xc, buffer, m.m_data, m.m_len);
- Trace::dataDump(curTick, xc->system->name(), (uint8_t *)buffer,
+ Trace::dataDump(curTick, xc->getSystemPtr()->name(), (uint8_t *)buffer,
m.m_len);
delete [] buffer;
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/printf.cc b/kern/tru64/printf.cc
index 12a089c40..77ac17c3a 100644
--- a/kern/tru64/printf.cc
+++ b/kern/tru64/printf.cc
@@ -32,8 +32,8 @@
#include "base/cprintf.hh"
#include "base/trace.hh"
#include "sim/host.hh"
-#include "targetarch/arguments.hh"
-#include "targetarch/vtophys.hh"
+#include "arch/arguments.hh"
+#include "arch/vtophys.hh"
using namespace std;
diff --git a/kern/tru64/tru64.hh b/kern/tru64/tru64.hh
index 07c0d21a7..112f00f31 100644
--- a/kern/tru64/tru64.hh
+++ b/kern/tru64/tru64.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,1297 @@
#ifndef __TRU64_HH__
#define __TRU64_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
class Tru64 {};
+#else //!FULL_SYSTEM
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h> // for memset()
+#include <unistd.h>
+
+#include "cpu/base.hh"
+#include "sim/root.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+
+typedef struct stat global_stat;
+typedef struct statfs global_statfs;
+typedef struct dirent global_dirent;
+
+///
+/// This class encapsulates the types, structures, constants,
+/// functions, and syscall-number mappings specific to the Alpha Tru64
+/// syscall interface.
+///
+class Tru64 {
+
+ public:
+
+ //@{
+ /// Basic Tru64 types.
+ typedef uint64_t size_t;
+ typedef uint64_t off_t;
+ typedef uint16_t nlink_t;
+ typedef int32_t dev_t;
+ typedef uint32_t uid_t;
+ typedef uint32_t gid_t;
+ typedef uint32_t time_t;
+ typedef uint32_t mode_t;
+ typedef uint32_t ino_t;
+ typedef struct { int val[2]; } quad;
+ typedef quad fsid_t;
+ //@}
+
+ //@{
+ /// open(2) flag values.
+ static const int TGT_O_RDONLY = 00000000;
+ static const int TGT_O_WRONLY = 00000001;
+ static const int TGT_O_RDWR = 00000002;
+ static const int TGT_O_NONBLOCK = 00000004;
+ static const int TGT_O_APPEND = 00000010;
+ static const int TGT_O_CREAT = 00001000;
+ static const int TGT_O_TRUNC = 00002000;
+ static const int TGT_O_EXCL = 00004000;
+ static const int TGT_O_NOCTTY = 00010000;
+ static const int TGT_O_SYNC = 00040000;
+ static const int TGT_O_DRD = 00100000;
+ static const int TGT_O_DIRECTIO = 00200000;
+ static const int TGT_O_CACHE = 00400000;
+ static const int TGT_O_DSYNC = 02000000;
+ static const int TGT_O_RSYNC = 04000000;
+ //@}
+
+ /// This table maps the target open() flags to the corresponding
+ /// host open() flags.
+ static OpenFlagTransTable openFlagTable[];
+
+ /// Number of entries in openFlagTable[].
+ static const int NUM_OPEN_FLAGS;
+
+ /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat
+ /// structure, and a new set of syscall numbers for stat calls.
+ /// On some hosts (notably Linux) define st_atime, st_mtime, and
+ /// st_ctime as macros, so we append an X to get around this.
+ struct F64_stat {
+ dev_t st_dev; //!< st_dev
+ int32_t st_retired1; //!< st_retired1
+ mode_t st_mode; //!< st_mode
+ nlink_t st_nlink; //!< st_nlink
+ uint16_t st_nlink_reserved; //!< st_nlink_reserved
+ uid_t st_uid; //!< st_uid
+ gid_t st_gid; //!< st_gid
+ dev_t st_rdev; //!< st_rdev
+ dev_t st_ldev; //!< st_ldev
+ off_t st_size; //!< st_size
+ time_t st_retired2; //!< st_retired2
+ int32_t st_uatime; //!< st_uatime
+ time_t st_retired3; //!< st_retired3
+ int32_t st_umtime; //!< st_umtime
+ time_t st_retired4; //!< st_retired4
+ int32_t st_uctime; //!< st_uctime
+ int32_t st_retired5; //!< st_retired5
+ int32_t st_retired6; //!< st_retired6
+ uint32_t st_flags; //!< st_flags
+ uint32_t st_gen; //!< st_gen
+ uint64_t st_spare[4]; //!< st_spare[4]
+ ino_t st_ino; //!< st_ino
+ int32_t st_ino_reserved; //!< st_ino_reserved
+ time_t st_atimeX; //!< st_atime
+ int32_t st_atime_reserved; //!< st_atime_reserved
+ time_t st_mtimeX; //!< st_mtime
+ int32_t st_mtime_reserved; //!< st_mtime_reserved
+ time_t st_ctimeX; //!< st_ctime
+ int32_t st_ctime_reserved; //!< st_ctime_reserved
+ uint64_t st_blksize; //!< st_blksize
+ uint64_t st_blocks; //!< st_blocks
+ };
+
+
+ /// Old Tru64 v4.x stat struct.
+ /// Tru64 maintains backwards compatibility with v4.x by
+ /// implementing another set of stat functions using the old
+ /// structure definition and binding them to the old syscall
+ /// numbers.
+
+ struct pre_F64_stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid __attribute__ ((aligned(sizeof(uid_t))));
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size __attribute__ ((aligned(sizeof(off_t))));
+ time_t st_atimeX;
+ int32_t st_uatime;
+ time_t st_mtimeX;
+ int32_t st_umtime;
+ time_t st_ctimeX;
+ int32_t st_uctime;
+ uint32_t st_blksize;
+ int32_t st_blocks;
+ uint32_t st_flags;
+ uint32_t st_gen;
+ };
+
+ /// For statfs().
+ struct F64_statfs {
+ int16_t f_type;
+ int16_t f_flags;
+ int32_t f_retired1;
+ int32_t f_retired2;
+ int32_t f_retired3;
+ int32_t f_retired4;
+ int32_t f_retired5;
+ int32_t f_retired6;
+ int32_t f_retired7;
+ fsid_t f_fsid;
+ int32_t f_spare[9];
+ char f_retired8[90];
+ char f_retired9[90];
+ uint64_t dummy[10]; // was union mount_info mount_info;
+ uint64_t f_flags2;
+ int64_t f_spare2[14];
+ int64_t f_fsize;
+ int64_t f_bsize;
+ int64_t f_blocks;
+ int64_t f_bfree;
+ int64_t f_bavail;
+ int64_t f_files;
+ int64_t f_ffree;
+ char f_mntonname[1024];
+ char f_mntfromname[1024];
+ };
+
+ /// For old Tru64 v4.x statfs()
+ struct pre_F64_statfs {
+ int16_t f_type;
+ int16_t f_flags;
+ int32_t f_fsize;
+ int32_t f_bsize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ int32_t f_spare[9];
+ char f_mntonname[90];
+ char f_mntfromname[90];
+ uint64_t dummy[10]; // was union mount_info mount_info;
+ };
+
+ /// For getdirentries().
+ struct dirent
+ {
+ ino_t d_ino; //!< file number of entry
+ uint16_t d_reclen; //!< length of this record
+ uint16_t d_namlen; //!< length of string in d_name
+ char d_name[256]; //!< dummy name length
+ };
+
+
+ /// Length of strings in struct utsname (plus 1 for null char).
+ static const int _SYS_NMLN = 32;
+
+ /// Interface struct for uname().
+ struct utsname {
+ char sysname[_SYS_NMLN]; //!< System name.
+ char nodename[_SYS_NMLN]; //!< Node name.
+ char release[_SYS_NMLN]; //!< OS release.
+ char version[_SYS_NMLN]; //!< OS version.
+ char machine[_SYS_NMLN]; //!< Machine type.
+ };
+
+ //@{
+ /// ioctl() command codes.
+ static const unsigned TIOCGETP = 0x40067408;
+ static const unsigned TIOCSETP = 0x80067409;
+ static const unsigned TIOCSETN = 0x8006740a;
+ static const unsigned TIOCSETC = 0x80067411;
+ static const unsigned TIOCGETC = 0x40067412;
+ static const unsigned FIONREAD = 0x4004667f;
+ static const unsigned TIOCISATTY = 0x2000745e;
+ // TIOCGETS not defined in tru64, so I made up a number
+ static const unsigned TIOCGETS = 0x40000000;
+ static const unsigned TIOCGETA = 0x402c7413;
+ //@}
+
+ /// Resource enumeration for getrlimit().
+ enum rlimit_resources {
+ TGT_RLIMIT_CPU = 0,
+ TGT_RLIMIT_FSIZE = 1,
+ TGT_RLIMIT_DATA = 2,
+ TGT_RLIMIT_STACK = 3,
+ TGT_RLIMIT_CORE = 4,
+ TGT_RLIMIT_RSS = 5,
+ TGT_RLIMIT_NOFILE = 6,
+ TGT_RLIMIT_AS = 7,
+ TGT_RLIMIT_VMEM = 7
+ };
+
+ /// Limit struct for getrlimit/setrlimit.
+ struct rlimit {
+ uint64_t rlim_cur; //!< soft limit
+ uint64_t rlim_max; //!< hard limit
+ };
+
+
+ /// For mmap().
+ static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+
+
+ //@{
+ /// For getsysinfo().
+ static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
+ static const unsigned GSI_CPU_INFO = 59; //!< CPU information
+ static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
+ static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
+ static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
+ static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
+ static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
+ //@}
+
+ /// For getsysinfo() GSI_CPU_INFO option.
+ struct cpu_info {
+ uint32_t current_cpu; //!< current_cpu
+ uint32_t cpus_in_box; //!< cpus_in_box
+ uint32_t cpu_type; //!< cpu_type
+ uint32_t ncpus; //!< ncpus
+ uint64_t cpus_present; //!< cpus_present
+ uint64_t cpus_running; //!< cpus_running
+ uint64_t cpu_binding; //!< cpu_binding
+ uint64_t cpu_ex_binding; //!< cpu_ex_binding
+ uint32_t mhz; //!< mhz
+ uint32_t unused[3]; //!< future expansion
+ };
+
+ //@{
+ /// For setsysinfo().
+ static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
+ //@}
+
+ /// For gettimeofday.
+ struct timeval {
+ uint32_t tv_sec; //!< seconds
+ uint32_t tv_usec; //!< microseconds
+ };
+
+ //@{
+ /// For getrusage().
+ static const int TGT_RUSAGE_THREAD = 1;
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
+ //@}
+
+ /// For getrusage().
+ struct rusage {
+ struct timeval ru_utime; //!< user time used
+ struct timeval ru_stime; //!< system time used
+ uint64_t ru_maxrss; //!< ru_maxrss
+ uint64_t ru_ixrss; //!< integral shared memory size
+ uint64_t ru_idrss; //!< integral unshared data "
+ uint64_t ru_isrss; //!< integral unshared stack "
+ uint64_t ru_minflt; //!< page reclaims - total vmfaults
+ uint64_t ru_majflt; //!< page faults
+ uint64_t ru_nswap; //!< swaps
+ uint64_t ru_inblock; //!< block input operations
+ uint64_t ru_oublock; //!< block output operations
+ uint64_t ru_msgsnd; //!< messages sent
+ uint64_t ru_msgrcv; //!< messages received
+ uint64_t ru_nsignals; //!< signals received
+ uint64_t ru_nvcsw; //!< voluntary context switches
+ uint64_t ru_nivcsw; //!< involuntary "
+ };
+
+ /// For sigreturn().
+ struct sigcontext {
+ int64_t sc_onstack; //!< sigstack state to restore
+ int64_t sc_mask; //!< signal mask to restore
+ int64_t sc_pc; //!< pc at time of signal
+ int64_t sc_ps; //!< psl to retore
+ int64_t sc_regs[32]; //!< processor regs 0 to 31
+ int64_t sc_ownedfp; //!< fp has been used
+ int64_t sc_fpregs[32]; //!< fp regs 0 to 31
+ uint64_t sc_fpcr; //!< floating point control reg
+ uint64_t sc_fp_control; //!< software fpcr
+ int64_t sc_reserved1; //!< reserved for kernel
+ uint32_t sc_kreserved1; //!< reserved for kernel
+ uint32_t sc_kreserved2; //!< reserved for kernel
+ size_t sc_ssize; //!< stack size
+ caddr_t sc_sbase; //!< stack start
+ uint64_t sc_traparg_a0; //!< a0 argument to trap on exc
+ uint64_t sc_traparg_a1; //!< a1 argument to trap on exc
+ uint64_t sc_traparg_a2; //!< a2 argument to trap on exc
+ uint64_t sc_fp_trap_pc; //!< imprecise pc
+ uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg
+ uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc
+ };
+
+
+ /// For table().
+ static const int TBL_SYSINFO = 12;
+
+ /// For table().
+ struct tbl_sysinfo {
+ uint64_t si_user; //!< User time
+ uint64_t si_nice; //!< Nice time
+ uint64_t si_sys; //!< System time
+ uint64_t si_idle; //!< Idle time
+ uint64_t si_hz; //!< hz
+ uint64_t si_phz; //!< phz
+ uint64_t si_boottime; //!< Boot time in seconds
+ uint64_t wait; //!< Wait time
+ uint32_t si_max_procs; //!< rpb->rpb_numprocs
+ uint32_t pad; //!< padding
+ };
+
+
+ /// For stack_create.
+ struct vm_stack {
+ // was void *
+ Addr address; //!< address hint
+ size_t rsize; //!< red zone size
+ size_t ysize; //!< yellow zone size
+ size_t gsize; //!< green zone size
+ size_t swap; //!< amount of swap to reserve
+ size_t incr; //!< growth increment
+ uint64_t align; //!< address alignment
+ uint64_t flags; //!< MAP_FIXED etc.
+ // was struct memalloc_attr *
+ Addr attr; //!< allocation policy
+ uint64_t reserved; //!< reserved
+ };
+
+ /// Return values for nxm calls.
+ enum {
+ KERN_NOT_RECEIVER = 7,
+ KERN_NOT_IN_SET = 12
+ };
+
+ /// For nxm_task_init.
+ static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP
+
+ /// Task attribute structure.
+ struct nxm_task_attr {
+ int64_t nxm_callback; //!< nxm_callback
+ unsigned int nxm_version; //!< nxm_version
+ unsigned short nxm_uniq_offset; //!< nxm_uniq_offset
+ unsigned short flags; //!< flags
+ int nxm_quantum; //!< nxm_quantum
+ int pad1; //!< pad1
+ int64_t pad2; //!< pad2
+ };
+
+ /// Signal set.
+ typedef uint64_t sigset_t;
+
+ /// Thread state shared between user & kernel.
+ struct ushared_state {
+ sigset_t sigmask; //!< thread signal mask
+ sigset_t sig; //!< thread pending mask
+ // struct nxm_pth_state *
+ Addr pth_id; //!< out-of-line state
+ int flags; //!< shared flags
+#define US_SIGSTACK 0x1 // thread called sigaltstack
+#define US_ONSTACK 0x2 // thread is running on altstack
+#define US_PROFILE 0x4 // thread called profil
+#define US_SYSCALL 0x8 // thread in syscall
+#define US_TRAP 0x10 // thread has trapped
+#define US_YELLOW 0x20 // thread has mellowed yellow
+#define US_YZONE 0x40 // thread has zoned out
+#define US_FP_OWNED 0x80 // thread used floating point
+
+ int cancel_state; //!< thread's cancelation state
+#define US_CANCEL 0x1 // cancel pending
+#define US_NOCANCEL 0X2 // synch cancel disabled
+#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled
+#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled
+#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
+#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
+ US_ASYNC_NOCANCEL)
+
+ // These are semi-shared. They are always visible to
+ // the kernel but are never context-switched by the library.
+
+ int nxm_ssig; //!< scheduler's synchronous signals
+ int reserved1; //!< reserved1
+ int64_t nxm_active; //!< scheduler active
+ int64_t reserved2; //!< reserved2
+ };
+
+ struct nxm_sched_state {
+ struct ushared_state nxm_u; //!< state own by user thread
+ unsigned int nxm_bits; //!< scheduler state / slot
+ int nxm_quantum; //!< quantum count-down value
+ int nxm_set_quantum; //!< quantum reset value
+ int nxm_sysevent; //!< syscall state
+ // struct nxm_upcall *
+ Addr nxm_uc_ret; //!< stack ptr of null thread
+ // void *
+ Addr nxm_tid; //!< scheduler's thread id
+ int64_t nxm_va; //!< page fault address
+ // struct nxm_pth_state *
+ Addr nxm_pthid; //!< id of null thread
+ uint64_t nxm_bound_pcs_count; //!< bound PCS thread count
+ int64_t pad[2]; //!< pad
+ };
+
+ /// nxm_shared.
+ struct nxm_shared {
+ int64_t nxm_callback; //!< address of upcall routine
+ unsigned int nxm_version; //!< version number
+ unsigned short nxm_uniq_offset; //!< correction factor for TEB
+ unsigned short pad1; //!< pad1
+ int64_t space[2]; //!< future growth
+ struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
+ };
+
+ /// nxm_slot_state_t.
+ enum nxm_slot_state_t {
+ NXM_SLOT_AVAIL,
+ NXM_SLOT_BOUND,
+ NXM_SLOT_UNBOUND,
+ NXM_SLOT_EMPTY
+ };
+
+ /// nxm_config_info
+ struct nxm_config_info {
+ int nxm_nslots_per_rad; //!< max number of VP slots per RAD
+ int nxm_nrads; //!< max number of RADs
+ // nxm_slot_state_t *
+ Addr nxm_slot_state; //!< per-VP slot state
+ // struct nxm_shared *
+ Addr nxm_rad[1]; //!< per-RAD shared areas
+ };
+
+ /// For nxm_thread_create.
+ enum nxm_thread_type {
+ NXM_TYPE_SCS = 0,
+ NXM_TYPE_VP = 1,
+ NXM_TYPE_MANAGER = 2
+ };
+
+ /// Thread attributes.
+ struct nxm_thread_attr {
+ int version; //!< version
+ int type; //!< type
+ int cancel_flags; //!< cancel_flags
+ int priority; //!< priority
+ int policy; //!< policy
+ int signal_type; //!< signal_type
+ // void *
+ Addr pthid; //!< pthid
+ sigset_t sigmask; //!< sigmask
+ /// Initial register values.
+ struct {
+ uint64_t pc; //!< pc
+ uint64_t sp; //!< sp
+ uint64_t a0; //!< a0
+ } registers;
+ uint64_t pad2[2]; //!< pad2
+ };
+
+ /// Helper function to convert a host stat buffer to a target stat
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by stat(), fstat(), and lstat().
+ template <class T>
+ static void
+ copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host)
+ {
+ TypedBufferArg<T> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+
+ /// Helper function to convert a host statfs buffer to a target statfs
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by statfs() and fstatfs().
+ template <class T>
+ static void
+ copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host)
+ {
+ TypedBufferArg<T> tgt(addr);
+
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
+ tgt->f_type = 0;
+#else
+ tgt->f_type = htog(host->f_type);
+#endif
+ tgt->f_bsize = htog(host->f_bsize);
+ tgt->f_blocks = htog(host->f_blocks);
+ tgt->f_bfree = htog(host->f_bfree);
+ tgt->f_bavail = htog(host->f_bavail);
+ tgt->f_files = htog(host->f_files);
+ tgt->f_ffree = htog(host->f_ffree);
+
+ // Is this as string normally?
+ memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
+
+ tgt.copyOut(mem);
+ }
+
+ class F64 {
+ public:
+ static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
+ global_stat *host)
+ {
+ Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host);
+ }
+
+ static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
+ global_statfs *host)
+ {
+ Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host);
+ }
+ };
+
+ class PreF64 {
+ public:
+ static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
+ global_stat *host)
+ {
+ Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host);
+ }
+
+ static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
+ global_statfs *host)
+ {
+ Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host);
+ }
+ };
+
+ /// Helper function to convert a host stat buffer to an old pre-F64
+ /// (4.x) target stat buffer. Also copies the target buffer out to
+ /// the simulated memory space. Used by pre_F64_stat(),
+ /// pre_F64_fstat(), and pre_F64_lstat().
+ static void
+ copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
+ {
+ TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+
+ /// Target getdirentries() handler.
+ static SyscallReturn
+ getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+#ifdef __CYGWIN__
+ panic("getdirent not implemented on cygwin!");
+#else
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+ Addr tgt_buf = xc->getSyscallArg(1);
+ int tgt_nbytes = xc->getSyscallArg(2);
+ Addr tgt_basep = xc->getSyscallArg(3);
+
+ char * const host_buf = new char[tgt_nbytes];
+
+ // just pass basep through uninterpreted.
+ TypedBufferArg<int64_t> basep(tgt_basep);
+ basep.copyIn(xc->getMemPtr());
+ long host_basep = (off_t)htog((int64_t)*basep);
+ int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
+
+ // check for error
+ if (host_result < 0) {
+ delete [] host_buf;
+ return -errno;
+ }
+
+ // no error: copy results back to target space
+ Addr tgt_buf_ptr = tgt_buf;
+ char *host_buf_ptr = host_buf;
+ char *host_buf_end = host_buf + host_result;
+ while (host_buf_ptr < host_buf_end) {
+ global_dirent *host_dp = (global_dirent *)host_buf_ptr;
+ int namelen = strlen(host_dp->d_name);
+
+ // Actual size includes padded string rounded up for alignment.
+ // Subtract 256 for dummy char array in Tru64::dirent definition.
+ // Add 1 to namelen for terminating null char.
+ int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
+ TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
+ tgt_dp->d_ino = host_dp->d_ino;
+ tgt_dp->d_reclen = tgt_bufsize;
+ tgt_dp->d_namlen = namelen;
+ strcpy(tgt_dp->d_name, host_dp->d_name);
+ tgt_dp.copyOut(xc->getMemPtr());
+
+ tgt_buf_ptr += tgt_bufsize;
+ host_buf_ptr += host_dp->d_reclen;
+ }
+
+ delete [] host_buf;
+
+ *basep = htog((int64_t)host_basep);
+ basep.copyOut(xc->getMemPtr());
+
+ return tgt_buf_ptr - tgt_buf;
+#endif
+ }
+
+ /// Target sigreturn() handler.
+ static SyscallReturn
+ sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using TheISA::RegFile;
+ TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
+
+ sc.copyIn(xc->getMemPtr());
+
+ // Restore state from sigcontext structure.
+ // Note that we'll advance PC <- NPC before the end of the cycle,
+ // so we need to restore the desired PC into NPC.
+ // The current regs->pc will get clobbered.
+ xc->setNextPC(htog(sc->sc_pc));
+
+ for (int i = 0; i < 31; ++i) {
+ xc->setIntReg(i, htog(sc->sc_regs[i]));
+ xc->setFloatRegInt(i, htog(sc->sc_fpregs[i]));
+ }
+
+ xc->setMiscReg(TheISA::Fpcr_DepTag, htog(sc->sc_fpcr));
+
+ return 0;
+ }
+
+ /// Target table() handler.
+ static SyscallReturn
+ tableFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ int id = xc->getSyscallArg(0); // table ID
+ int index = xc->getSyscallArg(1); // index into table
+ // arg 2 is buffer pointer; type depends on table ID
+ int nel = xc->getSyscallArg(3); // number of elements
+ int lel = xc->getSyscallArg(4); // expected element size
+
+ switch (id) {
+ case Tru64::TBL_SYSINFO: {
+ if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
+ return -EINVAL;
+ TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
+
+ const int clk_hz = one_million;
+ elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
+ elp->si_nice = htog(0);
+ elp->si_sys = htog(0);
+ elp->si_idle = htog(0);
+ elp->wait = htog(0);
+ elp->si_hz = htog(clk_hz);
+ elp->si_phz = htog(clk_hz);
+ elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch?
+ elp->si_max_procs = htog(process->numCpus());
+ elp.copyOut(xc->getMemPtr());
+ return 0;
+ }
+
+ default:
+ cerr << "table(): id " << id << " unknown." << endl;
+ return -EINVAL;
+ }
+ }
+
+ //
+ // Mach syscalls -- identified by negated syscall numbers
+ //
+
+ /// Create a stack region for a thread.
+ static SyscallReturn
+ stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
+
+ argp.copyIn(xc->getMemPtr());
+
+ // if the user chose an address, just let them have it. Otherwise
+ // pick one for them.
+ if (htog(argp->address) == 0) {
+ argp->address = htog(process->next_thread_stack_base);
+ int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
+ htog(argp->gsize));
+ process->next_thread_stack_base -= stack_size;
+ argp.copyOut(xc->getMemPtr());
+ }
+
+ return 0;
+ }
+
+ /// NXM library version stamp.
+ static
+ const int NXM_LIB_VERSION = 301003;
+
+ /// This call sets up the interface between the user and kernel
+ /// schedulers by creating a shared-memory region. The shared memory
+ /// region has several structs, some global, some per-RAD, some per-VP.
+ static SyscallReturn
+ nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
+ TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
+
+ attrp.copyIn(xc->getMemPtr());
+
+ if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
+ cerr << "nxm_task_init: thread library version mismatch! "
+ << "got " << attrp->nxm_version
+ << ", expected " << NXM_LIB_VERSION << endl;
+ abort();
+ }
+
+ if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) {
+ cerr << "nxm_task_init: bad flag value " << attrp->flags
+ << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
+ abort();
+ }
+
+ const Addr base_addr = 0x12000; // was 0x3f0000000LL;
+ Addr cur_addr = base_addr; // next addresses to use
+ // first comes the config_info struct
+ Addr config_addr = cur_addr;
+ cur_addr += sizeof(Tru64::nxm_config_info);
+ // next comes the per-cpu state vector
+ Addr slot_state_addr = cur_addr;
+ int slot_state_size =
+ process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+ cur_addr += slot_state_size;
+ // now the per-RAD state struct (we only support one RAD)
+ cur_addr = 0x14000; // bump up addr for alignment
+ Addr rad_state_addr = cur_addr;
+ int rad_state_size =
+ (sizeof(Tru64::nxm_shared)
+ + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+ cur_addr += rad_state_size;
+
+ // now initialize a config_info struct and copy it out to user space
+ TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
+
+ config->nxm_nslots_per_rad = htog(process->numCpus());
+ config->nxm_nrads = htog(1); // only one RAD in our system!
+ config->nxm_slot_state = htog(slot_state_addr);
+ config->nxm_rad[0] = htog(rad_state_addr);
+
+ config.copyOut(xc->getMemPtr());
+
+ // initialize the slot_state array and copy it out
+ TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
+ slot_state_size);
+ for (int i = 0; i < process->numCpus(); ++i) {
+ // CPU 0 is bound to the calling process; all others are available
+ // XXX this code should have an endian conversion, but I don't think
+ // it works anyway
+ slot_state[i] =
+ (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
+ }
+
+ slot_state.copyOut(xc->getMemPtr());
+
+ // same for the per-RAD "shared" struct. Note that we need to
+ // allocate extra bytes for the per-VP array which is embedded at
+ // the end.
+ TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
+ rad_state_size);
+
+ rad_state->nxm_callback = attrp->nxm_callback;
+ rad_state->nxm_version = attrp->nxm_version;
+ rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
+ for (int i = 0; i < process->numCpus(); ++i) {
+ Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
+ ssp->nxm_u.sigmask = htog(0);
+ ssp->nxm_u.sig = htog(0);
+ ssp->nxm_u.flags = htog(0);
+ ssp->nxm_u.cancel_state = htog(0);
+ ssp->nxm_u.nxm_ssig = 0;
+ ssp->nxm_bits = htog(0);
+ ssp->nxm_quantum = attrp->nxm_quantum;
+ ssp->nxm_set_quantum = attrp->nxm_quantum;
+ ssp->nxm_sysevent = htog(0);
+
+ if (i == 0) {
+ uint64_t uniq = xc->readMiscReg(TheISA::Uniq_DepTag);
+ ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset));
+ ssp->nxm_u.nxm_active = htog(uniq | 1);
+ }
+ else {
+ ssp->nxm_u.pth_id = htog(0);
+ ssp->nxm_u.nxm_active = htog(0);
+ }
+ }
+
+ rad_state.copyOut(xc->getMemPtr());
+
+ //
+ // copy pointer to shared config area out to user
+ //
+ *configptr_ptr = htog(config_addr);
+ configptr_ptr.copyOut(xc->getMemPtr());
+
+ // Register this as a valid address range with the process
+ process->nxm_start = base_addr;
+ process->nxm_end = cur_addr;
+
+ return 0;
+ }
+
+ /// Initialize execution context.
+ static void
+ init_exec_context(ExecContext *ec,
+ Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
+ {
+ ec->clearArchRegs();
+
+ ec->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0));
+ ec->setIntReg(27/*t12*/, gtoh(attrp->registers.pc));
+ ec->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));
+ ec->setMiscReg(TheISA::Uniq_DepTag, uniq_val);
+
+ ec->setPC(gtoh(attrp->registers.pc));
+ ec->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));
+
+ ec->activate();
+ }
+
+ /// Create thread.
+ static SyscallReturn
+ nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
+ TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
+ int thread_index = xc->getSyscallArg(2);
+
+ // get attribute args
+ attrp.copyIn(xc->getMemPtr());
+
+ if (gtoh(attrp->version) != NXM_LIB_VERSION) {
+ cerr << "nxm_thread_create: thread library version mismatch! "
+ << "got " << attrp->version
+ << ", expected " << NXM_LIB_VERSION << endl;
+ abort();
+ }
+
+ if (thread_index < 0 | thread_index > process->numCpus()) {
+ cerr << "nxm_thread_create: bad thread index " << thread_index
+ << endl;
+ abort();
+ }
+
+ // On a real machine, the per-RAD shared structure is in
+ // shared memory, so both the user and kernel can get at it.
+ // We don't have that luxury, so we just copy it in and then
+ // back out again.
+ int rad_state_size =
+ (sizeof(Tru64::nxm_shared) +
+ (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+
+ TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
+ rad_state_size);
+ rad_state.copyIn(xc->getMemPtr());
+
+ uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
+
+ if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) {
+ // DEC pthreads seems to always create one of these (in
+ // addition to N application threads), but we don't use it,
+ // so don't bother creating it.
+
+ // This is supposed to be a port number. Make something up.
+ *kidp = htog(99);
+ kidp.copyOut(xc->getMemPtr());
+
+ return 0;
+ } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
+ // A real "virtual processor" kernel thread. Need to fork
+ // this thread on another CPU.
+ Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
+
+ if (gtoh(ssp->nxm_u.nxm_active) != 0)
+ return (int) Tru64::KERN_NOT_RECEIVER;
+
+ ssp->nxm_u.pth_id = attrp->pthid;
+ ssp->nxm_u.nxm_active = htog(uniq_val | 1);
+
+ rad_state.copyOut(xc->getMemPtr());
+
+ Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
+ int slot_state_size =
+ process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+
+ TypedBufferArg<Tru64::nxm_slot_state_t>
+ slot_state(slot_state_addr,
+ slot_state_size);
+
+ slot_state.copyIn(xc->getMemPtr());
+
+ if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
+ cerr << "nxm_thread_createFunc: requested VP slot "
+ << thread_index << " not available!" << endl;
+ fatal("");
+ }
+
+ // XXX This should have an endian conversion but I think this code
+ // doesn't work anyway
+ slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
+
+ slot_state.copyOut(xc->getMemPtr());
+
+ // Find a free simulator execution context.
+ for (int i = 0; i < process->numCpus(); ++i) {
+ ExecContext *xc = process->execContexts[i];
+
+ if (xc->status() == ExecContext::Unallocated) {
+ // inactive context... grab it
+ init_exec_context(xc, attrp, uniq_val);
+
+ // This is supposed to be a port number, but we'll try
+ // and get away with just sticking the thread index
+ // here.
+ *kidp = htog(thread_index);
+ kidp.copyOut(xc->getMemPtr());
+
+ return 0;
+ }
+ }
+
+ // fell out of loop... no available inactive context
+ cerr << "nxm_thread_create: no idle contexts available." << endl;
+ abort();
+ } else {
+ cerr << "nxm_thread_create: can't handle thread type "
+ << attrp->type << endl;
+ abort();
+ }
+
+ return 0;
+ }
+
+ /// Thread idle call (like yield()).
+ static SyscallReturn
+ nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ return 0;
+ }
+
+ /// Block thread.
+ static SyscallReturn
+ nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ uint64_t tid = xc->getSyscallArg(0);
+ uint64_t secs = xc->getSyscallArg(1);
+ uint64_t flags = xc->getSyscallArg(2);
+ uint64_t action = xc->getSyscallArg(3);
+ uint64_t usecs = xc->getSyscallArg(4);
+
+ cout << xc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " "
+ << secs << " " << flags << " " << action << " " << usecs << endl;
+
+ return 0;
+ }
+
+ /// block.
+ static SyscallReturn
+ nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+ uint64_t val = xc->getSyscallArg(1);
+ uint64_t secs = xc->getSyscallArg(2);
+ uint64_t usecs = xc->getSyscallArg(3);
+ uint64_t flags = xc->getSyscallArg(4);
+
+ BaseCPU *cpu = xc->getCpuPtr();
+
+ cout << cpu->name() << ": nxm_block "
+ << hex << uaddr << dec << " " << val
+ << " " << secs << " " << usecs
+ << " " << flags << endl;
+
+ return 0;
+ }
+
+ /// Unblock thread.
+ static SyscallReturn
+ nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+
+ cout << xc->getCpuPtr()->name() << ": nxm_unblock "
+ << hex << uaddr << dec << endl;
+
+ return 0;
+ }
+
+ /// Switch thread priority.
+ static SyscallReturn
+ swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ // Attempts to switch to another runnable thread (if there is
+ // one). Returns false if there are no other threads to run
+ // (i.e., the thread can reasonably spin-wait) or true if there
+ // are other threads.
+ //
+ // Since we assume at most one "kernel" thread per CPU, it's
+ // always safe to return false here.
+ return 0; //false;
+ }
+
+
+ /// Activate exec context waiting on a channel. Just activate one
+ /// by default.
+ static int
+ activate_waiting_context(Addr uaddr, Process *process,
+ bool activate_all = false)
+ {
+ int num_activated = 0;
+
+ list<Process::WaitRec>::iterator i = process->waitList.begin();
+ list<Process::WaitRec>::iterator end = process->waitList.end();
+
+ while (i != end && (num_activated == 0 || activate_all)) {
+ if (i->waitChan == uaddr) {
+ // found waiting process: make it active
+ ExecContext *newCtx = i->waitingContext;
+ assert(newCtx->status() == ExecContext::Suspended);
+ newCtx->activate();
+
+ // get rid of this record
+ i = process->waitList.erase(i);
+
+ ++num_activated;
+ } else {
+ ++i;
+ }
+ }
+
+ return num_activated;
+ }
+
+ /// M5 hacked-up lock acquire.
+ static void
+ m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+ {
+ TypedBufferArg<uint64_t> lockp(uaddr);
+
+ lockp.copyIn(xc->getMemPtr());
+
+ if (gtoh(*lockp) == 0) {
+ // lock is free: grab it
+ *lockp = htog(1);
+ lockp.copyOut(xc->getMemPtr());
+ } else {
+ // lock is busy: disable until free
+ process->waitList.push_back(Process::WaitRec(uaddr, xc));
+ xc->suspend();
+ }
+ }
+
+ /// M5 unlock call.
+ static void
+ m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+ {
+ TypedBufferArg<uint64_t> lockp(uaddr);
+
+ lockp.copyIn(xc->getMemPtr());
+ assert(*lockp != 0);
+
+ // Check for a process waiting on the lock.
+ int num_waiting = activate_waiting_context(uaddr, process);
+
+ // clear lock field if no waiting context is taking over the lock
+ if (num_waiting == 0) {
+ *lockp = 0;
+ lockp.copyOut(xc->getMemPtr());
+ }
+ }
+
+ /// Lock acquire syscall handler.
+ static SyscallReturn
+ m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+
+ m5_lock_mutex(uaddr, process, xc);
+
+ // Return 0 since we will always return to the user with the lock
+ // acquired. We will just keep the context inactive until that is
+ // true.
+ return 0;
+ }
+
+ /// Try lock (non-blocking).
+ static SyscallReturn
+ m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+ TypedBufferArg<uint64_t> lockp(uaddr);
+
+ lockp.copyIn(xc->getMemPtr());
+
+ if (gtoh(*lockp) == 0) {
+ // lock is free: grab it
+ *lockp = htog(1);
+ lockp.copyOut(xc->getMemPtr());
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ /// Unlock syscall handler.
+ static SyscallReturn
+ m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+
+ m5_unlock_mutex(uaddr, process, xc);
+
+ return 0;
+ }
+
+ /// Signal ocndition.
+ static SyscallReturn
+ m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr cond_addr = xc->getSyscallArg(0);
+
+ // Wake up one process waiting on the condition variable.
+ activate_waiting_context(cond_addr, process);
+
+ return 0;
+ }
+
+ /// Wake up all processes waiting on the condition variable.
+ static SyscallReturn
+ m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr cond_addr = xc->getSyscallArg(0);
+
+ activate_waiting_context(cond_addr, process, true);
+
+ return 0;
+ }
+
+ /// Wait on a condition.
+ static SyscallReturn
+ m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr cond_addr = xc->getSyscallArg(0);
+ Addr lock_addr = xc->getSyscallArg(1);
+ TypedBufferArg<uint64_t> condp(cond_addr);
+ TypedBufferArg<uint64_t> lockp(lock_addr);
+
+ // user is supposed to acquire lock before entering
+ lockp.copyIn(xc->getMemPtr());
+ assert(gtoh(*lockp) != 0);
+
+ m5_unlock_mutex(lock_addr, process, xc);
+
+ process->waitList.push_back(Process::WaitRec(cond_addr, xc));
+ xc->suspend();
+
+ return 0;
+ }
+
+ /// Thread exit.
+ static SyscallReturn
+ m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ assert(xc->status() == ExecContext::Active);
+ xc->deallocate();
+
+ return 0;
+ }
+
+ /// Indirect syscall invocation (call #0).
+ static SyscallReturn
+ indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ int new_callnum = xc->getSyscallArg(0);
+ LiveProcess *lp = dynamic_cast<LiveProcess*>(process);
+ assert(lp);
+
+ for (int i = 0; i < 5; ++i)
+ xc->setSyscallArg(i, xc->getSyscallArg(i+1));
+
+
+ SyscallDesc *new_desc = lp->getDesc(new_callnum);
+ if (desc == NULL)
+ fatal("Syscall %d out of range", callnum);
+
+ new_desc->doSyscall(new_callnum, process, xc);
+
+ return 0;
+ }
+
+}; // class Tru64
+
+
+#endif // FULL_SYSTEM
+
#endif // __TRU64_HH__
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index 2079922b7..8f2be6d9b 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -33,8 +33,11 @@
#include "kern/tru64/dump_mbuf.hh"
#include "kern/tru64/printf.hh"
#include "mem/functional/memory_control.hh"
-#include "targetarch/arguments.hh"
-#include "targetarch/isa_traits.hh"
+#include "arch/arguments.hh"
+#include "arch/isa_traits.hh"
+#include "sim/system.hh"
+
+using namespace TheISA;
//void SkipFuncEvent::process(ExecContext *xc);
@@ -45,13 +48,14 @@ BadAddrEvent::process(ExecContext *xc)
// annotation for vmunix::badaddr in:
// simos/simulation/apps/tcl/osf/tlaser.tcl
- uint64_t a0 = xc->regs.intRegFile[ArgumentReg0];
+ uint64_t a0 = xc->readIntReg(ArgumentReg0);
if (!TheISA::IsK0Seg(a0) ||
- xc->memctrl->badaddr(TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
+ xc->getSystemPtr()->memctrl->badaddr(
+ TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0);
- xc->regs.intRegFile[ReturnValueReg] = 0x1;
+ xc->setIntReg(ReturnValueReg, 0x1);
SkipFuncEvent::process(xc);
}
else
@@ -62,7 +66,7 @@ void
PrintfEvent::process(ExecContext *xc)
{
if (DTRACE(Printf)) {
- DebugOut() << curTick << ": " << xc->cpu->name() << ": ";
+ DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
AlphaArguments args(xc);
tru64::Printf(args);
@@ -74,7 +78,7 @@ DebugPrintfEvent::process(ExecContext *xc)
{
if (DTRACE(DebugPrintf)) {
if (!raw)
- DebugOut() << curTick << ": " << xc->cpu->name() << ": ";
+ DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
AlphaArguments args(xc);
tru64::Printf(args);
diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py
index 2edc7576e..22714e15c 100644
--- a/python/m5/objects/Ethernet.py
+++ b/python/m5/objects/Ethernet.py
@@ -75,7 +75,6 @@ class EtherDevBase(PciDevice):
dma_write_delay = Param.Latency('0us', "fixed delay for dma writes")
dma_write_factor = Param.Latency('0us', "multiplier for dma writes")
dma_no_allocate = Param.Bool(True, "Should we allocate cache on read")
- pio_delay_write = Param.Bool(False, "Delay pio writes until timing occurs")
rx_delay = Param.Latency('1us', "Receive Delay")
tx_delay = Param.Latency('1us', "Transmit Delay")
@@ -86,6 +85,7 @@ class EtherDevBase(PciDevice):
intr_delay = Param.Latency('10us', "Interrupt propagation delay")
rx_thread = Param.Bool(False, "dedicated kernel thread for transmit")
tx_thread = Param.Bool(False, "dedicated kernel threads for receive")
+ rss = Param.Bool(False, "Receive Side Scaling")
class NSGigE(EtherDevBase):
type = 'NSGigE'
diff --git a/python/m5/objects/System.py b/python/m5/objects/System.py
index 8c5d93f7b..5925cadf5 100644
--- a/python/m5/objects/System.py
+++ b/python/m5/objects/System.py
@@ -1,19 +1,21 @@
from m5 import *
+
class System(SimObject):
type = 'System'
+ boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
+ "boot processor frequency")
+ memctrl = Param.MemoryController(Parent.any, "memory controller")
physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
+ init_param = Param.UInt64(0, "numerical value to pass into simulator")
+ bin = Param.Bool(False, "is this system binned")
+ binned_fns = VectorParam.String([], "functions broken down and binned")
+ kernel = Param.String("file that contains the kernel code")
+ readfile = Param.String("", "file to read startup script from")
- if build_env['FULL_SYSTEM']:
- boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
- "boot processor frequency")
- memctrl = Param.MemoryController(Parent.any, "memory controller")
- kernel = Param.String("file that contains the kernel code")
- console = Param.String("file that contains the console code")
- pal = Param.String("file that contains palcode")
- readfile = Param.String("", "file to read startup script from")
- init_param = Param.UInt64(0, "numerical value to pass into simulator")
- boot_osflags = Param.String("a", "boot flags to pass to the kernel")
- system_type = Param.UInt64("Type of system we are emulating")
- system_rev = Param.UInt64("Revision of system we are emulating")
- bin = Param.Bool(False, "is this system binned")
- binned_fns = VectorParam.String([], "functions broken down and binned")
+class AlphaSystem(System):
+ type = 'AlphaSystem'
+ console = Param.String("file that contains the console code")
+ pal = Param.String("file that contains palcode")
+ boot_osflags = Param.String("a", "boot flags to pass to the kernel")
+ system_type = Param.UInt64("Type of system we are emulating")
+ system_rev = Param.UInt64("Revision of system we are emulating")
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..701384989
--- /dev/null
+++ b/sim/faults.cc
@@ -0,0 +1,46 @@
+/*
+ * 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"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+
+#if !FULL_SYSTEM
+void FaultBase::invoke(ExecContext * xc)
+{
+ fatal("fault (%s) detected @ PC 0x%08p", name(), xc->readPC());
+}
+#else
+void FaultBase::invoke(ExecContext * xc)
+{
+ DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), xc->readPC());
+ xc->getCpuPtr()->recordEvent(csprintf("Fault %s", name()));
+
+ assert(!xc->misspeculating());
+}
+#endif
diff --git a/sim/faults.hh b/sim/faults.hh
new file mode 100644
index 000000000..18601e8f1
--- /dev/null
+++ b/sim/faults.hh
@@ -0,0 +1,67 @@
+/*
+ * 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__
+
+#include "base/refcnt.hh"
+#include "sim/stats.hh"
+#include "config/full_system.hh"
+
+class ExecContext;
+class FaultBase;
+typedef RefCountingPtr<FaultBase> Fault;
+
+typedef const char * FaultName;
+typedef Stats::Scalar<> FaultStat;
+
+// Each class has it's name statically define in _name,
+// and has a virtual function to access it's name.
+// The function is necessary because otherwise, all objects
+// which are being accessed cast as a FaultBase * (namely
+// all faults returned using the Fault type) will use the
+// generic FaultBase name.
+
+class FaultBase : public RefCounted
+{
+ public:
+ virtual FaultName name() = 0;
+#if FULL_SYSTEM
+ virtual void invoke(ExecContext * xc);
+#else
+ virtual void invoke(ExecContext * xc);
+#endif
+// template<typename T>
+// bool isA() {return dynamic_cast<T *>(this);}
+ virtual bool isMachineCheckFault() {return false;}
+ virtual bool isAlignmentFault() {return false;}
+};
+
+FaultBase * const NoFault = 0;
+
+#endif // __FAULTS_HH__
diff --git a/sim/host.hh b/sim/host.hh
index ef7008042..f7e64f23c 100644
--- a/sim/host.hh
+++ b/sim/host.hh
@@ -54,4 +54,12 @@ typedef int64_t Counter;
*/
typedef int64_t Tick;
+/**
+ * Address type
+ * This will probably be moved somewhere else in the near future.
+ * This should be at least as big as the biggest address width in use
+ * in the system, which will probably be 64 bits.
+ */
+typedef uint64_t Addr;
+
#endif // __HOST_H__
diff --git a/sim/process.cc b/sim/process.cc
index bb13bd35f..70a92a604 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -37,6 +37,7 @@
#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/smt.hh"
#include "encumbered/cpu/full/thread.hh"
@@ -48,14 +49,13 @@
#include "sim/fake_syscall.hh"
#include "sim/process.hh"
#include "sim/stats.hh"
+#include "sim/syscall_emul.hh"
#include "sim/system.hh"
-#ifdef TARGET_ALPHA
-#include "arch/alpha/alpha_tru64_process.hh"
-#include "arch/alpha/alpha_linux_process.hh"
-#endif
+#include "arch/process.hh"
using namespace std;
+using namespace TheISA;
//
// The purpose of this code is to fake the loader & syscall mechanism
@@ -247,8 +247,10 @@ static void
copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
TranslatingPort* memPort)
{
+ Addr data_ptr_swap;
for (int i = 0; i < strings.size(); ++i) {
- memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr));
+ data_ptr_swap = htog(data_ptr);
+ memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr));
memPort->writeStringFunctional(data_ptr, strings[i].c_str());
array_ptr += sizeof(Addr);
data_ptr += strings[i].size() + 1;
@@ -342,23 +344,35 @@ LiveProcess::startup()
// write contents to stack
uint64_t argc = argv.size();
+ argc = htog(argc);
initVirtMem->writeBlobFunctional(stack_min, (uint8_t*)&argc, sizeof(uint64_t));
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
- RegFile *init_regs = &(execContexts[0]->regs);
-
- init_regs->intRegFile[ArgumentReg0] = argc;
- init_regs->intRegFile[ArgumentReg1] = argv_array_base;
- init_regs->intRegFile[StackPointerReg] = stack_min;
- init_regs->intRegFile[GlobalPointerReg] = objFile->globalPointer();
- init_regs->pc = prog_entry;
- init_regs->npc = prog_entry + sizeof(MachInst);
+ execContexts[0]->setIntReg(ArgumentReg0, argc);
+ execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
+ execContexts[0]->setIntReg(StackPointerReg, stack_min);
+ execContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer());
+ execContexts[0]->setPC(prog_entry);
+ execContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
num_processes++;
}
+void
+LiveProcess::syscall(ExecContext *xc)
+{
+ num_syscalls++;
+
+ int64_t callnum = xc->readIntReg(SyscallNumReg);
+
+ SyscallDesc *desc = getDesc(callnum);
+ if (desc == NULL)
+ fatal("Syscall %d out of range", callnum);
+
+ desc->doSyscall(callnum, this, xc);
+}
LiveProcess *
LiveProcess::create(const string &nm, System *system,
@@ -372,30 +386,10 @@ LiveProcess::create(const string &nm, System *system,
fatal("Can't load object file %s", executable);
}
- // check object type & set up syscall emulation pointer
- if (objFile->getArch() == ObjectFile::Alpha) {
-
- switch (objFile->getOpSys()) {
- case ObjectFile::Tru64:
- process = new AlphaTru64Process(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
-
- break;
-
- case ObjectFile::Linux:
- process = new AlphaLinuxProcess(nm, objFile, system,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
-
- break;
-
- default:
- fatal("Unknown/unsupported operating system.");
- }
- } else {
- fatal("Unknown object file architecture.");
- }
+ // set up syscall emulation pointer for the current ISA
+ process = createProcess(nm, objFile, system,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
if (process == NULL)
fatal("Unknown error creating process object.");
@@ -404,6 +398,7 @@ LiveProcess::create(const string &nm, System *system,
}
+
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
VectorParam<string> cmd;
diff --git a/sim/process.hh b/sim/process.hh
index 8d8c9e676..fc600fb06 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -40,6 +40,7 @@
#include <vector>
+#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "base/trace.hh"
#include "mem/memory.hh"
@@ -49,12 +50,17 @@
#include "sim/stats.hh"
#include "targetarch/isa_traits.hh"
+class CPUExecContext;
class ExecContext;
+class SyscallDesc;
class TranslatingPort;
class System;
class Process : public SimObject
{
+ protected:
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MachInst MachInst;
public:
/// Pointer to object representing the system this process is
@@ -216,6 +222,11 @@ class LiveProcess : public Process
std::string executable,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
+
+ virtual void syscall(ExecContext *xc);
+
+ virtual SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); }
+
};
diff --git a/arch/alpha/pseudo_inst.cc b/sim/pseudo_inst.cc
index e105b3cc8..e475006e7 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/sim/pseudo_inst.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@
#include <string>
-#include "arch/alpha/pseudo_inst.hh"
-#include "arch/alpha/vtophys.hh"
+#include "sim/pseudo_inst.hh"
+#include "arch/vtophys.hh"
#include "cpu/base.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/exec_context.hh"
@@ -46,13 +46,14 @@
#include "sim/stats.hh"
#include "sim/system.hh"
#include "sim/debug.hh"
-#include "targetarch/vptr.hh"
+#include "sim/vptr.hh"
using namespace std;
extern Sampler *SampCPU;
using namespace Stats;
+using namespace TheISA;
namespace AlphaPseudo
{
@@ -63,7 +64,7 @@ namespace AlphaPseudo
void
arm(ExecContext *xc)
{
- xc->kernelStats->arm();
+ xc->getCpuPtr()->kernelStats->arm();
}
void
@@ -73,13 +74,55 @@ namespace AlphaPseudo
return;
xc->suspend();
- xc->kernelStats->quiesce();
+ xc->getCpuPtr()->kernelStats->quiesce();
+ }
+
+ void
+ quiesceNs(ExecContext *xc, uint64_t ns)
+ {
+ if (!doQuiesce || ns == 0)
+ return;
+
+ Event *quiesceEvent = xc->getQuiesceEvent();
+
+ if (quiesceEvent->scheduled())
+ quiesceEvent->reschedule(curTick + Clock::Int::ns * ns);
+ else
+ quiesceEvent->schedule(curTick + Clock::Int::ns * ns);
+
+ xc->suspend();
+ xc->getCpuPtr()->kernelStats->quiesce();
+ }
+
+ void
+ quiesceCycles(ExecContext *xc, uint64_t cycles)
+ {
+ if (!doQuiesce || cycles == 0)
+ return;
+
+ Event *quiesceEvent = xc->getQuiesceEvent();
+
+ if (quiesceEvent->scheduled())
+ quiesceEvent->reschedule(curTick +
+ xc->getCpuPtr()->cycles(cycles));
+ else
+ quiesceEvent->schedule(curTick +
+ xc->getCpuPtr()->cycles(cycles));
+
+ xc->suspend();
+ xc->getCpuPtr()->kernelStats->quiesce();
+ }
+
+ uint64_t
+ quiesceTime(ExecContext *xc)
+ {
+ return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns;
}
void
ivlb(ExecContext *xc)
{
- xc->kernelStats->ivlb();
+ xc->getCpuPtr()->kernelStats->ivlb();
}
void
@@ -94,21 +137,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 +158,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,26 +172,23 @@ 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);
- xc->system->kernelSymtab->insert(addr,symbol);
+ xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
}
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 +198,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 +210,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;
+ const string &file = xc->getCpuPtr()->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 +242,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..4dd427c99 100644
--- a/arch/alpha/pseudo_inst.hh
+++ b/sim/pseudo_inst.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -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
{
/**
@@ -39,16 +44,19 @@ namespace AlphaPseudo
void arm(ExecContext *xc);
void quiesce(ExecContext *xc);
+ void quiesceNs(ExecContext *xc, uint64_t ns);
+ void quiesceCycles(ExecContext *xc, uint64_t cycles);
+ uint64_t quiesceTime(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 0cebee0e1..1d0b3a375 100644
--- a/sim/syscall_emul.cc
+++ b/sim/syscall_emul.cc
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <fcntl.h>
#include <unistd.h>
#include <string>
@@ -40,17 +41,18 @@
#include "sim/sim_events.hh"
using namespace std;
+using namespace TheISA;
void
SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
{
DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
- xc->cpu->name(), name);
+ xc->getCpuPtr()->name(), name);
SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
- xc->cpu->name(), name, retval.value());
+ xc->getCpuPtr()->name(), name, retval.value());
if (!(flags & SyscallDesc::SuppressReturnValue))
xc->setSyscallReturn(retval);
@@ -89,7 +91,7 @@ exitFunc(SyscallDesc *desc, int callnum, Process *process,
SyscallReturn
getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
- return VMPageSize;
+ return (int)VMPageSize;
}
@@ -191,7 +193,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return (TheISA::IntReg)-EFAULT;
int result = unlink(path.c_str());
@@ -203,12 +205,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string old_name;
- if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
string new_name;
- if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != No_Fault)
+ if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != NoFault)
return -EFAULT;
int64_t result = rename(old_name.c_str(), new_name.c_str());
@@ -220,7 +222,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
off_t length = xc->getSyscallArg(1);
@@ -248,7 +250,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
/* XXX endianess */
@@ -278,3 +280,162 @@ fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
int result = fchown(fd, hostOwner, hostGroup);
return (result == -1) ? -errno : result;
}
+
+
+SyscallReturn
+fcntlFunc(SyscallDesc *desc, int num, Process *process,
+ ExecContext *xc)
+{
+ int fd = xc->getSyscallArg(0);
+
+ if (fd < 0 || process->sim_fd(fd) < 0)
+ return -EBADF;
+
+ int cmd = xc->getSyscallArg(1);
+ switch (cmd) {
+ case 0: // F_DUPFD
+ // if we really wanted to support this, we'd need to do it
+ // in the target fd space.
+ warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
+ return -EMFILE;
+
+ case 1: // F_GETFD (get close-on-exec flag)
+ case 2: // F_SETFD (set close-on-exec flag)
+ return 0;
+
+ case 3: // F_GETFL (get file flags)
+ case 4: // F_SETFL (set file flags)
+ // not sure if this is totally valid, but we'll pass it through
+ // to the underlying OS
+ warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
+ return fcntl(process->sim_fd(fd), cmd);
+ // return 0;
+
+ case 7: // F_GETLK (get lock)
+ case 8: // F_SETLK (set lock)
+ case 9: // F_SETLKW (set lock and wait)
+ // don't mess with file locking... just act like it's OK
+ warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
+ return 0;
+
+ default:
+ warn("Unknown fcntl command %d\n", cmd);
+ return 0;
+ }
+}
+
+SyscallReturn
+pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fds[2], sim_fds[2];
+ int pipe_retval = pipe(fds);
+
+ if (pipe_retval < 0) {
+ // error
+ return pipe_retval;
+ }
+
+ sim_fds[0] = process->alloc_fd(fds[0]);
+ sim_fds[1] = process->alloc_fd(fds[1]);
+
+ // Alpha Linux convention for pipe() is that fd[0] is returned as
+ // the return value of the function, and fd[1] is returned in r20.
+ xc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]);
+ return sim_fds[0];
+}
+
+
+SyscallReturn
+getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Make up a PID. There's no interprocess communication in
+ // fake_syscall mode, so there's no way for a process to know it's
+ // not getting a unique value.
+
+ xc->setIntReg(SyscallPseudoReturnReg, 99);
+ return 100;
+}
+
+
+SyscallReturn
+getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Make up a UID and EUID... it shouldn't matter, and we want the
+ // simulation to be deterministic.
+
+ // EUID goes in r20.
+ xc->setIntReg(SyscallPseudoReturnReg, 100); //EUID
+ return 100; // UID
+}
+
+
+SyscallReturn
+getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Get current group ID. EGID goes in r20.
+ xc->setIntReg(SyscallPseudoReturnReg, 100); //EGID
+ return 100;
+}
+
+
+SyscallReturn
+setuidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // can't fathom why a benchmark would call this.
+ warn("Ignoring call to setuid(%d)\n", xc->getSyscallArg(0));
+ return 0;
+}
+
+SyscallReturn
+getpidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Make up a PID. There's no interprocess communication in
+ // fake_syscall mode, so there's no way for a process to know it's
+ // not getting a unique value.
+
+ xc->setIntReg(SyscallPseudoReturnReg, 99); //PID
+ return 100;
+}
+
+SyscallReturn
+getppidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 99;
+}
+
+SyscallReturn
+getuidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100; // UID
+}
+
+SyscallReturn
+geteuidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100; // UID
+}
+
+SyscallReturn
+getgidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100;
+}
+
+SyscallReturn
+getegidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100;
+}
+
+
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
index ed3b0fc8b..25f8c6cb8 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/translating_port.hh"
-#include "targetarch/isa_traits.hh" // for Addr
+#include "arch/isa_traits.hh" // for Addr
#include "base/trace.hh"
#include "cpu/exec_context.hh"
@@ -237,6 +240,58 @@ SyscallReturn chownFunc(SyscallDesc *desc, int num,
SyscallReturn fchownFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
+/// Target fnctl() handler.
+SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
+ Process *process, ExecContext *xc);
+
+/// Target setuid() handler.
+SyscallReturn setuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getpid() handler.
+SyscallReturn getpidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getuid() handler.
+SyscallReturn getuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getgid() handler.
+SyscallReturn getgidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getppid() handler.
+SyscallReturn getppidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target geteuid() handler.
+SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getegid() handler.
+SyscallReturn getegidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+
+/// Pseudo Funcs - These functions use a different return convension,
+/// returning a second value in a register other than the normal return register
+SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
+ Process *process, ExecContext *xc);
+
+/// Target getpidPseudo() handler.
+SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getuidPseudo() handler.
+SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getgidPseudo() handler.
+SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
/// This struct is used to build an target-OS-dependent table that
/// maps the target's open() flags to the host open() flags.
struct OpenFlagTransTable {
@@ -315,7 +370,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
if (path == "/dev/sysdev0") {
@@ -362,7 +417,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
uint32_t mode = xc->getSyscallArg(1);
@@ -374,7 +429,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
// do the chmod
int result = chmod(path.c_str(), hostMode);
if (result < 0)
- return errno;
+ return -errno;
return 0;
}
@@ -401,7 +456,7 @@ fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
// do the fchmod
int result = fchmod(process->sim_fd(fd), hostMode);
if (result < 0)
- return errno;
+ return -errno;
return 0;
}
@@ -415,14 +470,14 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct stat hostBuf;
int result = stat(path.c_str(), &hostBuf);
if (result < 0)
- return errno;
+ return -errno;
OS::copyOutStatBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
@@ -442,13 +497,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;
+ return -errno;
- OS::copyOutStat64Buf(xc->port, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->port, fd, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -462,7 +522,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct stat hostBuf;
@@ -484,16 +544,21 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(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->port, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->port, -1, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -531,14 +596,14 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct statfs hostBuf;
int result = statfs(path.c_str(), &hostBuf);
if (result < 0)
- return errno;
+ return -errno;
OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
@@ -561,7 +626,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
int result = fstatfs(fd, &hostBuf);
if (result < 0)
- return errno;
+ return -errno;
OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
@@ -589,9 +654,9 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
typename OS::tgt_iovec tiov;
xc->port->readBlobFunctional(tiov_base + i*sizeof(typename OS::tgt_iovec),(uint8_t*)
&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->port->readBlobFunctional(tiov.iov_base,
+ xc->port->readBlobFunctional(gtoh(tiov.iov_base),
(uint8_t *)hiov[i].iov_base, hiov[i].iov_len);
}
@@ -603,7 +668,7 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
}
if (result < 0)
- return errno;
+ return -errno;
return 0;
}
@@ -635,7 +700,7 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
if (start == 0) {
// user didn't give an address... pick one from our "mmap region"
start = p->mmap_end;
- p->mmap_end += roundUp(length, VMPageSize);
+ p->mmap_end += roundUp(length, TheISA::VMPageSize);
if (p->nxm_start != 0) {
//If we have an nxm space, make sure we haven't colided
assert(p->mmap_end < p->nxm_start);
@@ -654,22 +719,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->port);
@@ -680,12 +747,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->port);
@@ -701,7 +770,7 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
@@ -710,8 +779,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);
@@ -720,7 +789,6 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
return 0;
}
-
/// Target getrusage() function.
template <class OS>
SyscallReturn
@@ -730,7 +798,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.",
@@ -738,6 +806,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 07eb81c71..3ed7ed590 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -1,36 +1,11 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * 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 "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh"
+#include "arch/vtophys.hh"
#include "mem/memory.hh"
#include "sim/builder.hh"
+#include "arch/isa_traits.hh"
+#include "sim/byteswap.hh"
#include "sim/system.hh"
#include "base/trace.hh"
#if FULL_SYSTEM
@@ -41,6 +16,7 @@
#endif
using namespace std;
+using namespace TheISA;
vector<System *> System::systemList;
@@ -53,39 +29,24 @@ System::System(Params *p)
#else
page_ptr(0),
#endif
- params(p)
+ _params(p)
{
// add self to global system list
systemList.push_back(this);
#if FULL_SYSTEM
kernelSymtab = new SymbolTable;
- consoleSymtab = new SymbolTable;
- palSymtab = new SymbolTable;
debugSymbolTable = new SymbolTable;
/**
- * Load the kernel, pal, and console code into memory
+ * Load the kernel code into memory
*/
// Load kernel code
- kernel = createObjectFile(params->kernel_path);
+ kernel = createObjectFile(params()->kernel_path);
if (kernel == NULL)
- fatal("Could not load kernel file %s", params->kernel_path);
-
- // Load Console Code
- console = createObjectFile(params->console_path);
- if (console == NULL)
- fatal("Could not load console file %s", params->console_path);
-
- // Load pal file
- pal = createObjectFile(params->palcode);
- if (pal == NULL)
- fatal("Could not load PALcode file %s", params->palcode);
-
+ fatal("Could not load kernel file %s", params()->kernel_path);
// Load program sections into memory
- pal->loadSections(physmem, true);
- console->loadSections(physmem, true);
kernel->loadSections(physmem, true);
// setup entry points
@@ -100,73 +61,19 @@ System::System(Params *p)
if (!kernel->loadLocalSymbols(kernelSymtab))
panic("could not load kernel local symbols\n");
- if (!console->loadGlobalSymbols(consoleSymtab))
- panic("could not load console symbols\n");
-
- if (!pal->loadGlobalSymbols(palSymtab))
- panic("could not load pal symbols\n");
-
- if (!pal->loadLocalSymbols(palSymtab))
- panic("could not load pal symbols\n");
-
if (!kernel->loadGlobalSymbols(debugSymbolTable))
panic("could not load kernel symbols\n");
if (!kernel->loadLocalSymbols(debugSymbolTable))
panic("could not load kernel local symbols\n");
- if (!console->loadGlobalSymbols(debugSymbolTable))
- panic("could not load console symbols\n");
-
- if (!pal->loadGlobalSymbols(debugSymbolTable))
- panic("could not load pal symbols\n");
-
- if (!pal->loadLocalSymbols(debugSymbolTable))
- panic("could not load pal symbols\n");
-
-
DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
DPRINTF(Loader, "Kernel loaded...\n");
- Addr addr = 0;
-#ifdef DEBUG
- consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
-#endif
-
- /**
- * Copy the osflags (kernel arguments) into the consoles
- * memory. (Presently Linux does not use the console service
- * routine to get these command line arguments, but Tru64 and
- * others do.)
- */
- if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
- Addr paddr = vtophys(physmem, addr);
- char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
-
- if (osflags)
- strcpy(osflags, params->boot_osflags.c_str());
- }
-
- /**
- * Set the hardware reset parameter block system type and revision
- * information to Tsunami.
- */
- if (consoleSymtab->findAddress("m5_rpb", addr)) {
- Addr paddr = vtophys(physmem, addr);
- char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (!hwrpb)
- panic("could not translate hwrpb addr\n");
-
- *(uint64_t*)(hwrpb+0x50) = htog(params->system_type);
- *(uint64_t*)(hwrpb+0x58) = htog(params->system_rev);
- } else
- panic("could not find hwrpb\n");
-
+#if FULL_SYSTEM
kernelBinning = new Kernel::Binning(this);
-
#endif // FULL_SYSTEM
// increment the number of running systms
@@ -177,77 +84,9 @@ System::~System()
{
#if FULL_SYSTEM
delete kernelSymtab;
- delete consoleSymtab;
delete kernel;
- delete console;
- delete pal;
delete kernelBinning;
-
-#ifdef DEBUG
- delete consolePanicEvent;
-#endif
-
-#endif // FULL_SYSTEM
-}
-
-
-/**
- * This function fixes up addresses that are used to match PCs for
- * hooking simulator events on to target function executions.
- *
- * Alpha binaries may have multiple global offset table (GOT)
- * sections. A function that uses the GOT starts with a
- * two-instruction prolog which sets the global pointer (gp == r29) to
- * the appropriate GOT section. The proper gp value is calculated
- * based on the function address, which must be passed by the caller
- * in the procedure value register (pv aka t12 == r27). This sequence
- * looks like the following:
- *
- * opcode Ra Rb offset
- * ldah gp,X(pv) 09 29 27 X
- * lda gp,Y(gp) 08 29 29 Y
- *
- * for some constant offsets X and Y. The catch is that the linker
- * (or maybe even the compiler, I'm not sure) may recognize that the
- * caller and callee are using the same GOT section, making this
- * prolog redundant, and modify the call target to skip these
- * instructions. If we check for execution of the first instruction
- * of a function (the one the symbol points to) to detect when to skip
- * it, we'll miss all these modified calls. It might work to
- * unconditionally check for the third instruction, but not all
- * functions have this prolog, and there's some chance that those
- * first two instructions could have undesired consequences. So we do
- * the Right Thing and pattern-match the first two instructions of the
- * function to decide where to patch.
- *
- * Eventually this code should be moved into an ISA-specific file.
- */
-Addr
-System::fixFuncEventAddr(Addr addr)
-{
-#if FULL_SYSTEM
- // mask for just the opcode, Ra, and Rb fields (not the offset)
- const uint32_t inst_mask = 0xffff0000;
- // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
- const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
- // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
- const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
- // instruction size
- const int sz = sizeof(uint32_t);
-
- Addr paddr = vtophys(physmem, addr);
- uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz);
- uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz);
-
- if ((i1 & inst_mask) == gp_ldah_pattern &&
- (i2 & inst_mask) == gp_lda_pattern) {
- Addr new_addr = addr + 2*sz;
- DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
- return new_addr;
- } else {
- return addr;
- }
#else
panic("System::fixFuncEventAddr needs to be rewritten "
"to work with syscall emulation");
@@ -255,29 +94,7 @@ System::fixFuncEventAddr(Addr addr)
}
#if FULL_SYSTEM
-void
-System::setAlphaAccess(Addr access)
-{
- Addr addr = 0;
- if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
- Addr paddr = vtophys(physmem, addr);
- uint64_t *m5AlphaAccess =
- (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (!m5AlphaAccess)
- panic("could not translate m5AlphaAccess addr\n");
-
- *m5AlphaAccess = htog(EV5::Phys2K0Seg(access));
- } else
- panic("could not find m5AlphaAccess\n");
-}
-
-bool
-System::breakpoint()
-{
- return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
-}
int rgdb_wait = -1;
@@ -326,11 +143,9 @@ System::registerExecContext(ExecContext *xc, int id)
void
System::startup()
{
- if (!execContexts.empty()) {
- // activate with zero delay so that we start ticking right
- // away on cycle 0
- execContexts[0]->activate(0);
- }
+ int i;
+ for (i = 0; i < execContexts.size(); i++)
+ execContexts[i]->activate(0);
}
void
@@ -372,8 +187,6 @@ System::serialize(ostream &os)
kernelBinning->serialize(os);
kernelSymtab->serialize("kernel_symtab", os);
- consoleSymtab->serialize("console_symtab", os);
- palSymtab->serialize("pal_symtab", os);
#endif // FULL_SYSTEM
}
@@ -385,8 +198,6 @@ System::unserialize(Checkpoint *cp, const string &section)
kernelBinning->unserialize(cp, section);
kernelSymtab->unserialize("kernel_symtab", cp, section);
- consoleSymtab->unserialize("console_symtab", cp, section);
- palSymtab->unserialize("pal_symtab", cp, section);
#endif // FULL_SYSTEM
}
@@ -408,78 +219,5 @@ printSystems()
System::printSystems();
}
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
-
- SimObjectParam<Memory *> physmem;
-
-#if FULL_SYSTEM
- Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
-
- Param<string> kernel;
- Param<string> console;
- Param<string> pal;
-
- Param<string> boot_osflags;
- Param<string> readfile;
- Param<unsigned int> init_param;
-
- Param<uint64_t> system_type;
- Param<uint64_t> system_rev;
-
- Param<bool> bin;
- VectorParam<string> binned_fns;
- Param<bool> bin_int;
-#endif // FULL_SYSTEM
-
-END_DECLARE_SIM_OBJECT_PARAMS(System)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(System)
-
- INIT_PARAM(physmem, "physical memory")
-
-#if FULL_SYSTEM
- ,
- INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
- INIT_PARAM(memctrl, "memory controller"),
- INIT_PARAM(kernel, "file that contains the kernel code"),
- INIT_PARAM(console, "file that contains the console code"),
- INIT_PARAM(pal, "file that contains palcode"),
- INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a"),
- INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
- INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
-#endif // FULL_SYSTEM
-
-END_INIT_SIM_OBJECT_PARAMS(System)
-
-CREATE_SIM_OBJECT(System)
-{
- System::Params *p = new System::Params;
- p->name = getInstanceName();
- p->physmem = physmem;
-#if FULL_SYSTEM
- p->boot_cpu_frequency = boot_cpu_frequency;
- p->memctrl = memctrl;
- p->kernel_path = kernel;
- p->console_path = console;
- p->palcode = pal;
- p->boot_osflags = boot_osflags;
- p->init_param = init_param;
- p->readfile = readfile;
- p->system_type = system_type;
- p->system_rev = system_rev;
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
-#endif // FULL_SYSTEM
- return new System(p);
-}
-
-REGISTER_SIM_OBJECT("System", System)
+DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
diff --git a/sim/system.hh b/sim/system.hh
index 8922373cc..cbe876c42 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -78,21 +78,9 @@ class System : public SimObject
/** kernel symbol table */
SymbolTable *kernelSymtab;
- /** console symbol table */
- SymbolTable *consoleSymtab;
-
- /** pal symbol table */
- SymbolTable *palSymtab;
-
/** Object pointer for the kernel code */
ObjectFile *kernel;
- /** Object pointer for the console code */
- ObjectFile *console;
-
- /** Object pointer for the PAL code */
- ObjectFile *pal;
-
/** Begining of kernel code */
Addr kernelStart;
@@ -104,11 +92,6 @@ class System : public SimObject
Kernel::Binning *kernelBinning;
-#ifdef DEBUG
- /** Event to halt the simulator if the console calls panic() */
- BreakPCEvent *consolePanicEvent;
-#endif
-
#else
int page_ptr;
@@ -123,7 +106,7 @@ class System : public SimObject
* events on to target function executions. See comment in
* system.cc for details.
*/
- Addr fixFuncEventAddr(Addr addr);
+ virtual Addr fixFuncEventAddr(Addr addr) = 0;
/**
* Add a function-based event to the given function, to be looked
@@ -150,26 +133,12 @@ class System : public SimObject
return addFuncEvent<T>(kernelSymtab, lbl);
}
- /** Add a function-based event to PALcode. */
- template <class T>
- T *System::addPalFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(palSymtab, lbl);
- }
-
- /** Add a function-based event to the console code. */
- template <class T>
- T *System::addConsoleFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(consoleSymtab, lbl);
- }
#endif
-
public:
#if FULL_SYSTEM
std::vector<RemoteGDB *> remoteGDB;
std::vector<GDBListener *> gdbListen;
- bool breakpoint();
+ virtual bool breakpoint() = 0;
#endif // FULL_SYSTEM
public:
@@ -187,31 +156,25 @@ class System : public SimObject
bool bin_int;
std::string kernel_path;
- std::string console_path;
- std::string palcode;
- std::string boot_osflags;
-
std::string readfile;
- uint64_t system_type;
- uint64_t system_rev;
#endif
};
- Params *params;
+ protected:
+ Params *_params;
+
+ public:
System(Params *p);
~System();
void startup();
+ const Params *params() const { return (const Params *)_params; }
+
public:
#if FULL_SYSTEM
/**
- * Set the m5AlphaAccess pointer in the console
- */
- void setAlphaAccess(Addr access);
-
- /**
* Returns the addess the kernel starts at.
* @return address the kernel starts at
*/
@@ -253,6 +216,8 @@ class System : public SimObject
static int numSystemsRunning;
static void printSystems();
+
+
};
#endif // __SYSTEM_HH__
diff --git a/arch/alpha/vptr.hh b/sim/vptr.hh
index d1bda4061..0ec452f25 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 "arch/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)
diff --git a/util/m5/Makefile b/util/m5/Makefile
index 6e4ad31a3..518542322 100644
--- a/util/m5/Makefile
+++ b/util/m5/Makefile
@@ -1,26 +1,50 @@
-AS=as
-CC=cc
-LD=cc
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# 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.
-CCFLAGS=-O2
-#LDFLAGS=-non_shared
+### If we are not compiling on an alpha, we must use cross tools ###
+ifneq ($(shell uname -m), alpha)
+CROSS_COMPILE?=alpha-unknown-linux-gnu-
+endif
+CC=$(CROSS_COMPILE)gcc
+AS=$(CROSS_COMPILE)as
+LD=$(CROSS_COMPILE)ld
-all: m5
+CFLAGS=-O2
+OBJS=m5.o m5op.o
-m5: m5op.o m5.o
- $(LD) $(LDFLAGS) -o $@ $>
- strip $@
+all: m5
-clean:
- @rm -f m5 *.o *.d *~ .#*
+%.o: %.S
+ $(CC) $(CFLAGS) -o $@ -c $<
-.SUFFIXES:
-.SUFFIXES:.o .c .s
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $<
-# C Compilation
-.c.o:
- $(CC) $(CCFLAGS) -o $@ -c $<
+m5: $(OBJS)
+ $(CC) -o $@ $(OBJS)
-# Assembly
-.s.o:
- $(AS) $(ASFLAGS) -o $@ $<
+clean:
+ rm -f *.o m5
diff --git a/util/m5/m5.c b/util/m5/m5.c
index 942ad5ba4..6fdbc0500 100644
--- a/util/m5/m5.c
+++ b/util/m5/m5.c
@@ -73,7 +73,7 @@ main(int argc, char *argv[])
usage();
arg1 = strtoul(argv[2], NULL, 0);
- ivlb(arg1);
+ m5_ivlb(arg1);
return 0;
}
@@ -82,7 +82,7 @@ main(int argc, char *argv[])
usage();
arg1 = strtoul(argv[2], NULL, 0);
- ivle(arg1);
+ m5_ivle(arg1);
return 0;
}
@@ -90,7 +90,7 @@ main(int argc, char *argv[])
if (argc != 2)
usage();
- printf("%ld", initparam());
+ printf("%ld", m5_initparam());
return 0;
}
@@ -98,7 +98,7 @@ main(int argc, char *argv[])
if (argc != 2)
usage();
- param = initparam();
+ param = m5_initparam();
// run-time, rampup-time, rampdown-time, warmup-time, connections
printf("%d %d %d %d %d", (param >> 48) & 0xfff,
(param >> 36) & 0xfff, (param >> 24) & 0xfff,
@@ -112,7 +112,7 @@ main(int argc, char *argv[])
case 3:
arg1 = strtoul(argv[2], NULL, 0);
case 2:
- m5exit(arg1);
+ m5_exit(arg1);
return 0;
default:
@@ -127,7 +127,7 @@ main(int argc, char *argv[])
case 3:
arg1 = strtoul(argv[2], NULL, 0);
case 2:
- reset_stats(arg1, arg2);
+ m5_reset_stats(arg1, arg2);
return 0;
default:
@@ -142,7 +142,7 @@ main(int argc, char *argv[])
case 3:
arg1 = strtoul(argv[2], NULL, 0);
case 2:
- dump_stats(arg1, arg2);
+ m5_dump_stats(arg1, arg2);
return 0;
default:
@@ -157,7 +157,7 @@ main(int argc, char *argv[])
case 3:
arg1 = strtoul(argv[2], NULL, 0);
case 2:
- dumpreset_stats(arg1, arg2);
+ m5_dumpreset_stats(arg1, arg2);
return 0;
default:
@@ -172,7 +172,7 @@ main(int argc, char *argv[])
case 3:
arg1 = strtoul(argv[2], NULL, 0);
case 2:
- checkpoint(arg1, arg2);
+ m5_checkpoint(arg1, arg2);
return 0;
default:
diff --git a/util/m5/m5op.S b/util/m5/m5op.S
new file mode 100644
index 000000000..a53c45277
--- /dev/null
+++ b/util/m5/m5op.S
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define m5_op 0x01
+
+#define arm_func 0x00
+#define quiesce_func 0x01
+#define quiescens_func 0x02
+#define quiescecycle_func 0x03
+#define quiescetime_func 0x04
+#define ivlb_func 0x10
+#define ivle_func 0x11
+#define exit_old_func 0x20 // deprectated!
+#define exit_func 0x21
+#define initparam_func 0x30
+#define resetstats_func 0x40
+#define dumpstats_func 0x41
+#define dumprststats_func 0x42
+#define ckpt_func 0x43
+#define readfile_func 0x50
+#define debugbreak_func 0x51
+#define switchcpu_func 0x52
+#define addsymbol_func 0x53
+#define panic_func 0x54
+
+#define INST(op, ra, rb, func) \
+ .long (((op) << 26) | ((ra) << 21) | ((rb) << 16) | (func))
+
+#define LEAF(func) \
+ .align 3; \
+ .globl func; \
+ .ent func; \
+func:
+
+#define RET \
+ ret ($26)
+
+#define END(func) \
+ .end func
+
+#define ARM(reg) INST(m5_op, reg, 0, arm_func)
+#define QUIESCE INST(m5_op, 0, 0, quiesce_func)
+#define QUIESCENS(r1) INST(m5_op, r1, 0, quiescens_func)
+#define QUIESCECYC(r1) INST(m5_op, r1, 0, quiescecycle_func)
+#define QUIESCETIME INST(m5_op, 0, 0, quiescetime_func)
+#define IVLB(reg) INST(m5_op, reg, 0, ivlb_func)
+#define IVLE(reg) INST(m5_op, reg, 0, ivle_func)
+#define M5EXIT(reg) INST(m5_op, reg, 0, exit_func)
+#define INITPARAM(reg) INST(m5_op, reg, 0, initparam_func)
+#define RESET_STATS(r1, r2) INST(m5_op, r1, r2, resetstats_func)
+#define DUMP_STATS(r1, r2) INST(m5_op, r1, r2, dumpstats_func)
+#define DUMPRST_STATS(r1, r2) INST(m5_op, r1, r2, dumprststats_func)
+#define CHECKPOINT(r1, r2) INST(m5_op, r1, r2, ckpt_func)
+#define READFILE INST(m5_op, 0, 0, readfile_func)
+#define DEBUGBREAK INST(m5_op, 0, 0, debugbreak_func)
+#define SWITCHCPU INST(m5_op, 0, 0, switchcpu_func)
+#define ADDSYMBOL(r1,r2) INST(m5_op, r1, r2, addsymbol_func)
+#define PANIC INST(m5_op, 0, 0, panic_func)
+
+ .set noreorder
+
+ .align 4
+LEAF(arm)
+ ARM(16)
+ RET
+END(arm)
+
+ .align 4
+LEAF(quiesce)
+ QUIESCE
+ RET
+END(quiesce)
+
+ .align 4
+LEAF(quiesceNs)
+ QUIESCENS(16)
+ RET
+END(quiesceNs)
+
+ .align 4
+LEAF(quiesceCycle)
+ QUIESCECYC(16)
+ RET
+END(quiesceCycle)
+
+ .align 4
+LEAF(quiesceTime)
+ QUIESCETIME
+ RET
+END(quiesceTime)
+
+
+ .align 4
+LEAF(m5_ivlb)
+ IVLB(16)
+ RET
+END(m5_ivlb)
+
+ .align 4
+LEAF(m5_ivle)
+ IVLE(16)
+ RET
+END(m5_ivle)
+
+ .align 4
+LEAF(m5_exit)
+ M5EXIT(16)
+ RET
+END(m5_exit)
+
+ .align 4
+LEAF(m5_initparam)
+ INITPARAM(0)
+ RET
+END(m5_initparam)
+
+ .align 4
+LEAF(m5_reset_stats)
+ RESET_STATS(16, 17)
+ RET
+END(m5_reset_stats)
+
+ .align 4
+LEAF(m5_dump_stats)
+ DUMP_STATS(16, 17)
+ RET
+END(m5_dump_stats)
+
+ .align 4
+LEAF(m5_dumpreset_stats)
+ DUMPRST_STATS(16, 17)
+ RET
+END(m5_dumpreset_stats)
+
+ .align 4
+LEAF(m5_checkpoint)
+ CHECKPOINT(16, 17)
+ RET
+END(m5_checkpoint)
+
+ .align 4
+LEAF(m5_readfile)
+ READFILE
+ RET
+END(m5_readfile)
+
+ .align 4
+LEAF(m5_debugbreak)
+ DEBUGBREAK
+ RET
+END(m5_debugbreak)
+
+ .align 4
+LEAF(m5_switchcpu)
+ SWITCHCPU
+ RET
+END(m5_switchcpu)
+
+ .align 4
+LEAF(m5_addsymbol)
+ ADDSYMBOL(16, 17)
+ RET
+END(m5_addsymbol)
+
+ .align 4
+LEAF(m5_panic)
+ PANIC
+ RET
+END(m5_panic)
+
+
diff --git a/util/m5/m5op.h b/util/m5/m5op.h
index 91dc4cc8b..34ac7760d 100644
--- a/util/m5/m5op.h
+++ b/util/m5/m5op.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,26 @@
#ifndef __M5OP_H__
#define __M5OP_H__
-#include <inttypes.h>
+#include <asm/types.h>
void arm(uint64_t address);
-void quiesce();
-void ivlb(uint64_t interval);
-void ivle(uint64_t interval);
-void m5exit(uint64_t ns_delay);
-uint64_t initparam();
-void checkpoint(uint64_t ns_delay, uint64_t ns_period);
-void reset_stats(uint64_t ns_delay, uint64_t ns_period);
-void dump_stats(uint64_t ns_delay, uint64_t ns_period);
-void dumpreset_stats(uint64_t ns_delay, uint64_t ns_period);
+void quiesce(void);
+void quiesceNs(uint64_t ns);
+void quiesceCycle(uint64_t cycles);
+uint64_t quiesceTime(void);
+
+void m5_ivlb(uint64_t interval);
+void m5_ivle(uint64_t interval);
+void m5_exit(uint64_t ns_delay);
+uint64_t m5_initparam(void);
+void m5_checkpoint(uint64_t ns_delay, uint64_t ns_period);
+void m5_reset_stats(uint64_t ns_delay, uint64_t ns_period);
+void m5_dump_stats(uint64_t ns_delay, uint64_t ns_period);
+void m5_dumpreset_stats(uint64_t ns_delay, uint64_t ns_period);
+uint64_t m5_readfile(void *buffer, uint64_t len, uint64_t offset);
+void m5_debugbreak(void);
+void m5_switchcpu(void);
+void m5_addsymbol(uint64_t addr, char *symbol);
+void m5_panic(void);
#endif // __M5OP_H__
diff --git a/util/m5/m5op.s b/util/m5/m5op.s
deleted file mode 100644
index e779e4209..000000000
--- a/util/m5/m5op.s
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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 <machine/asm.h>
-#include <regdef.h>
-
-#define m5_op 0x01
-
-#define arm_func 0x00
-#define quiesce_func 0x01
-#define ivlb_func 0x10
-#define ivle_func 0x11
-#define exit_old_func 0x20 // deprectated!
-#define exit_func 0x21
-#define initparam_func 0x30
-#define resetstats_func 0x40
-#define dumpstats_func 0x41
-#define dumprststats_func 0x42
-#define ckpt_func 0x43
-
-#define INST(op, ra, rb, func) \
- .long (((op) << 26) | ((ra) << 21) | ((rb) << 16) | (func))
-
-#define ARM(reg) INST(m5_op, reg, 0, arm_func)
-#define QUIESCE() INST(m5_op, 0, 0, quiesce_func)
-#define IVLB(reg) INST(m5_op, reg, 0, ivlb_func)
-#define IVLE(reg) INST(m5_op, reg, 0, ivle_func)
-#define M5EXIT(reg) INST(m5_op, reg, 0, exit_func)
-#define INITPARAM(reg) INST(m5_op, reg, 0, initparam_func)
-#define RESET_STATS(r1, r2) INST(m5_op, r1, r2, resetstats_func)
-#define DUMP_STATS(r1, r2) INST(m5_op, r1, r2, dumpstats_func)
-#define DUMPRST_STATS(r1, r2) INST(m5_op, r1, r2, dumprststats_func)
-#define CHECKPOINT(r1, r2) INST(m5_op, r1, r2, ckpt_func)
-
- .set noreorder
-
- .align 4
-LEAF(arm)
- ARM(16)
- RET
-END(arm)
-
- .align 4
-LEAF(quiesce)
- QUIESCE()
- RET
-END(quiesce)
-
- .align 4
-LEAF(ivlb)
- IVLB(16)
- RET
-END(ivlb)
-
- .align 4
-LEAF(ivle)
- IVLE(16)
- RET
-END(ivle)
-
- .align 4
-LEAF(m5exit)
- M5EXIT(16)
- RET
-END(m5exit)
-
- .align 4
-LEAF(initparam)
- INITPARAM(0)
- RET
-END(initparam)
-
- .align 4
-LEAF(reset_stats)
- RESET_STATS(16, 17)
- RET
-END(reset_stats)
-
- .align 4
-LEAF(dump_stats)
- DUMP_STATS(16, 17)
- RET
-END(dump_stats)
-
- .align 4
-LEAF(dumpreset_stats)
- DUMPRST_STATS(16, 17)
- RET
-END(dumpreset_stats)
-
- .align 4
-LEAF(checkpoint)
- CHECKPOINT(16, 17)
- RET
-END(checkpoint)
-
diff --git a/util/pbs/jobfile.py b/util/pbs/jobfile.py
index d36b5ee6d..fd19b3bf5 100644
--- a/util/pbs/jobfile.py
+++ b/util/pbs/jobfile.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 The Regents of The University of Michigan
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -277,10 +277,11 @@ class Option(Data):
return name
if attr == 'desc':
- desc = self.__dict__[attr]
- if self._suboption is not None:
- desc = '%s, %s' % (desc, self._suboption.desc)
- return desc
+ desc = [ self.__dict__[attr] ]
+ if self._suboption is not None and self._suboption.desc:
+ desc.append(self._suboption.desc)
+ return ', '.join(desc)
+
return super(Option, self).__getattribute__(attr)
@@ -356,6 +357,8 @@ class Configuration(Data):
def __init__(self, name, desc, **kwargs):
super(Configuration, self).__init__(name, desc, **kwargs)
self._groups = []
+ self._posfilters = []
+ self._negfilters = []
def group(self, name, desc, **kwargs):
grp = Group(name, desc, **kwargs)
@@ -402,13 +405,39 @@ class Configuration(Data):
if checkpoint:
yield options
+ def addfilter(self, filt, pos=True):
+ import re
+ filt = re.compile(filt)
+ if pos:
+ self._posfilters.append(filt)
+ else:
+ self._negfilters.append(filt)
+
+ def jobfilter(self, job):
+ for filt in self._negfilters:
+ if filt.match(job.name):
+ return False
+
+ if not self._posfilters:
+ return True
+
+ for filt in self._posfilters:
+ if filt.match(job.name):
+ return True
+
+ return False
+
def checkpoints(self, groups = None):
for options in self.options(groups, True):
- yield Job(options)
+ job = Job(options)
+ if self.jobfilter(job):
+ yield job
def jobs(self, groups = None):
for options in self.options(groups, False):
- yield Job(options)
+ job = Job(options)
+ if self.jobfilter(job):
+ yield job
def alljobs(self, groups = None):
for options in self.options(groups, True):
diff --git a/util/stats/barchart.py b/util/stats/barchart.py
index 19cccb58a..5d6dd0ab1 100644
--- a/util/stats/barchart.py
+++ b/util/stats/barchart.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 The Regents of The University of Michigan
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@ import matplotlib, pylab
from matplotlib.font_manager import FontProperties
from matplotlib.numerix import array, arange, reshape, shape, transpose, zeros
from matplotlib.numerix import Float
+from matplotlib.ticker import NullLocator
matplotlib.interactive(False)
@@ -41,13 +42,18 @@ class BarChart(ChartOptions):
super(BarChart, self).__init__(default, **kwargs)
self.inputdata = None
self.chartdata = None
+ self.inputerr = None
+ self.charterr = None
def gen_colors(self, count):
cmap = matplotlib.cm.get_cmap(self.colormap)
if count == 1:
return cmap([ 0.5 ])
- else:
- return cmap(arange(count) / float(count - 1))
+
+ if count < 5:
+ return cmap(arange(5) / float(4))[:count]
+
+ return cmap(arange(count) / float(count - 1))
# The input data format does not match the data format that the
# graph function takes because it is intuitive. The conversion
@@ -88,6 +94,32 @@ class BarChart(ChartOptions):
data = property(get_data, set_data)
+ def set_err(self, err):
+ if err is None:
+ self.inputerr = None
+ self.charterr = None
+ return
+
+ err = array(err)
+ dim = len(shape(err))
+ if dim not in (1, 2, 3):
+ raise AttributeError, "Input err must be a 1, 2, or 3d matrix"
+ self.inputerr = err
+
+ if dim == 1:
+ self.charterr = array([[err]])
+
+ if dim == 2:
+ self.charterr = transpose([err], axes=(2,0,1))
+
+ if dim == 3:
+ self.charterr = transpose(err, axes=(1,2,0))
+
+ def get_err(self):
+ return self.inputerr
+
+ err = property(get_err, set_err)
+
# Graph the chart data.
# Input is a 3d matrix that describes a plot that has multiple
# groups, multiple bars in each group, and multiple values stacked
@@ -120,11 +152,11 @@ class BarChart(ChartOptions):
if self.chartdata is None:
raise AttributeError, "Data not set for bar chart!"
- self.figure = pylab.figure(figsize=self.chart_size)
- self.axes = self.figure.add_axes(self.figure_size)
-
dim = len(shape(self.inputdata))
cshape = shape(self.chartdata)
+ if self.charterr is not None and shape(self.charterr) != cshape:
+ raise AttributeError, 'Dimensions of error and data do not match'
+
if dim == 1:
colors = self.gen_colors(cshape[2])
colors = [ [ colors ] * cshape[1] ] * cshape[0]
@@ -139,13 +171,36 @@ class BarChart(ChartOptions):
colors = array(colors)
- bars_in_group = len(self.chartdata)
- if bars_in_group < 5:
- width = 1.0 / ( bars_in_group + 1)
- center = width / 2
+ self.figure = pylab.figure(figsize=self.chart_size)
+
+ outer_axes = None
+ inner_axes = None
+ if self.xsubticks is not None:
+ color = self.figure.get_facecolor()
+ self.metaaxes = self.figure.add_axes(self.figure_size,
+ axisbg=color, frameon=False)
+ for tick in self.metaaxes.xaxis.majorTicks:
+ tick.tick1On = False
+ tick.tick2On = False
+ self.metaaxes.set_yticklabels([])
+ self.metaaxes.set_yticks([])
+ size = [0] * 4
+ size[0] = self.figure_size[0]
+ size[1] = self.figure_size[1] + .12
+ size[2] = self.figure_size[2]
+ size[3] = self.figure_size[3] - .12
+ self.axes = self.figure.add_axes(size)
+ outer_axes = self.metaaxes
+ inner_axes = self.axes
else:
- width = .8 / bars_in_group
- center = .1
+ self.axes = self.figure.add_axes(self.figure_size)
+ outer_axes = self.axes
+ inner_axes = self.axes
+
+ bars_in_group = len(self.chartdata)
+
+ width = 1.0 / ( bars_in_group + 1)
+ center = width / 2
bars = []
for i,stackdata in enumerate(self.chartdata):
@@ -154,30 +209,42 @@ class BarChart(ChartOptions):
for j,bardata in enumerate(stackdata):
bardata = array(bardata)
ind = arange(len(bardata)) + i * width + center
+ yerr = None
+ if self.charterr is not None:
+ yerr = self.charterr[i][j]
bar = self.axes.bar(ind, bardata, width, bottom=bottom,
- color=colors[i][j])
+ color=colors[i][j], yerr=yerr)
+ if self.xsubticks is not None:
+ self.metaaxes.bar(ind, [0] * len(bardata), width)
stack.append(bar)
bottom += bardata
bars.append(stack)
if self.xlabel is not None:
- self.axes.set_xlabel(self.xlabel)
+ outer_axes.set_xlabel(self.xlabel)
if self.ylabel is not None:
- self.axes.set_ylabel(self.ylabel)
+ inner_axes.set_ylabel(self.ylabel)
if self.yticks is not None:
ymin, ymax = self.axes.get_ylim()
nticks = float(len(self.yticks))
ticks = arange(nticks) / (nticks - 1) * (ymax - ymin) + ymin
- self.axes.set_yticks(ticks)
- self.axes.set_yticklabels(self.yticks)
+ inner_axes.set_yticks(ticks)
+ inner_axes.set_yticklabels(self.yticks)
elif self.ylim is not None:
- self.axes.set_ylim(self.ylim)
+ self.inner_axes.set_ylim(self.ylim)
if self.xticks is not None:
- self.axes.set_xticks(arange(cshape[2]) + .5)
- self.axes.set_xticklabels(self.xticks)
+ outer_axes.set_xticks(arange(cshape[2]) + .5)
+ outer_axes.set_xticklabels(self.xticks)
+
+ if self.xsubticks is not None:
+ numticks = (cshape[0] + 1) * cshape[2]
+ inner_axes.set_xticks(arange(numticks) * width + 2 * center)
+ self.xsubticks.append('')
+ inner_axes.set_xticklabels(self.xsubticks * cshape[2], fontsize=7,
+ rotation=90)
if self.legend is not None:
if dim == 1:
@@ -188,8 +255,12 @@ class BarChart(ChartOptions):
number = len(bars[0])
lbars = [ bars[0][number - j - 1][0] for j in xrange(number)]
- self.figure.legend(lbars, self.legend, self.legend_loc,
- prop=FontProperties(size=self.legend_size))
+ if self.fig_legend:
+ self.figure.legend(lbars, self.legend, self.legend_loc,
+ prop=FontProperties(size=self.legend_size))
+ else:
+ self.axes.legend(lbars, self.legend, self.legend_loc,
+ prop=FontProperties(size=self.legend_size))
if self.title is not None:
self.axes.set_title(self.title)
@@ -213,14 +284,13 @@ class BarChart(ChartOptions):
ylabel = []
#if self.ylabel:
# ylabel = [ self.ylabel[i] ]
- f.write(', '.join(ylabel + [ '%f' % val for val in row]) + '\n')
+ f.write(', '.join(ylabel + [ '%f' % v for v in row]) + '\n')
if dim == 3:
f.write("don't do 3D csv files\n")
pass
f.close()
-
if __name__ == '__main__':
from random import randrange
import random, sys
@@ -252,6 +322,8 @@ if __name__ == '__main__':
chart1.legend = [ 'x%d' % x for x in xrange(myshape[-1]) ]
chart1.xticks = [ 'xtick%d' % x for x in xrange(myshape[0]) ]
chart1.title = 'this is the title'
+ if len(myshape) > 2:
+ chart1.xsubticks = [ '%d' % x for x in xrange(myshape[1]) ]
chart1.graph()
chart1.savefig('/tmp/test1.png')
chart1.savefig('/tmp/test1.ps')
@@ -266,4 +338,4 @@ if __name__ == '__main__':
chart2.savefig('/tmp/test2.png')
chart2.savefig('/tmp/test2.ps')
- #pylab.show()
+# pylab.show()
diff --git a/util/stats/categories.py b/util/stats/categories.py
index 8d5d506a2..6d8568879 100644
--- a/util/stats/categories.py
+++ b/util/stats/categories.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 The Regents of The University of Michigan
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,10 +33,14 @@ func_categories = { \
'skb_clone_fraglist' : 'buffer',
'skb_seq_read' : 'buffer',
'sock_alloc_send_skb' : 'buffer',
+ 'sinic_rxskb_alloc' : 'buffer',
# Copy functions
+ 'sinic_copyfrom' : 'copy',
'__copy_user' : 'copy',
'skb_copy_bits' : 'copy',
+ 'skb_copy_datagram_iovec' : 'copy',
+ 'sinic_vcopy_iov' : 'idle',
# Driver functions
'do_tx_done' : 'driver',
diff --git a/util/stats/chart.py b/util/stats/chart.py
index 1e301cb58..369a57fc6 100644
--- a/util/stats/chart.py
+++ b/util/stats/chart.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 The Regents of The University of Michigan
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@ class ChartOptions(object):
defaults = { 'chart_size' : (8, 4),
'figure_size' : [0.1, 0.1, 0.6, 0.85],
'title' : None,
+ 'fig_legend' : True,
'legend' : None,
'legend_loc' : 'upper right',
'legend_size' : 6,
@@ -38,6 +39,7 @@ class ChartOptions(object):
'xlabel' : None,
'ylabel' : None,
'xticks' : None,
+ 'xsubticks' : None,
'yticks' : None,
'ylim' : None,
}
diff --git a/util/stats/db.py b/util/stats/db.py
index d9b78c7d1..c0e7796eb 100644
--- a/util/stats/db.py
+++ b/util/stats/db.py
@@ -158,7 +158,7 @@ class Database(object):
return None
from info import ProxyError, scalar, vector, value, values, total, len
- if system is None and hasattr('system', job):
+ if system is None and hasattr(job, 'system'):
system = job.system
if system is not None:
diff --git a/util/stats/output.py b/util/stats/output.py
index e67751bbc..abfb8d901 100644
--- a/util/stats/output.py
+++ b/util/stats/output.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 The Regents of The University of Michigan
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -103,15 +103,17 @@ class StatOutput(ChartOptions):
else:
groups.append(group)
- if not groupopts:
- raise AttributeError, 'No group selected for graph group'
+ has_group = bool(groupopts)
+ if has_group:
+ groupopts = [ group for group in crossproduct(groupopts) ]
+ else:
+ groupopts = [ None ]
- if not baropts:
+ if baropts:
+ baropts = [ bar for bar in crossproduct(baropts) ]
+ else:
raise AttributeError, 'No group selected for graph bars'
- groupopts = [ group for group in crossproduct(groupopts) ]
- baropts = [ bar for bar in crossproduct(baropts) ]
-
directory = expanduser(graphdir)
if not isdir(directory):
os.mkdir(directory)
@@ -124,12 +126,13 @@ class StatOutput(ChartOptions):
for options in self.jobfile.options(groups):
chart = BarChart(self)
- data = zeros((len(groupopts), len(baropts)), Float)
data = [ [ None ] * len(baropts) for i in xrange(len(groupopts)) ]
enabled = False
stacked = 0
for g,gopt in enumerate(groupopts):
for b,bopt in enumerate(baropts):
+ if gopt is None:
+ gopt = []
job = self.jobfile.job(options + gopt + bopt)
if not job:
continue
@@ -168,19 +171,24 @@ class StatOutput(ChartOptions):
if data.sum() == 0:
continue
+ dim = len(data.shape)
x = data.shape[0]
- y = data.shape[1]
xkeep = [ i for i in xrange(x) if data[i].sum() != 0 ]
+ y = data.shape[1]
ykeep = [ i for i in xrange(y) if data[:,i].sum() != 0 ]
data = data.take(xkeep, axis=0)
data = data.take(ykeep, axis=1)
+ if not has_group:
+ data = data.take([ 0 ], axis=0)
chart.data = data
- gopts = [ groupopts[i] for i in xkeep ]
- bopts = [ baropts[i] for i in ykeep ]
+ bopts = [ baropts[i] for i in ykeep ]
bdescs = [ ' '.join([o.desc for o in opt]) for opt in bopts]
- gdescs = [ ' '.join([o.desc for o in opt]) for opt in gopts]
+
+ if has_group:
+ gopts = [ groupopts[i] for i in xkeep ]
+ gdescs = [ ' '.join([o.desc for o in opt]) for opt in gopts]
if chart.legend is None:
if stacked:
@@ -192,7 +200,10 @@ class StatOutput(ChartOptions):
chart.legend = bdescs
if chart.xticks is None:
- chart.xticks = gdescs
+ if has_group:
+ chart.xticks = gdescs
+ else:
+ chart.xticks = []
chart.graph()
names = [ opt.name for opt in options ]
diff --git a/util/stats/stats.py b/util/stats/stats.py
index b75d9fec0..08281287f 100755
--- a/util/stats/stats.py
+++ b/util/stats/stats.py
@@ -262,6 +262,7 @@ def commands(options, command, args):
from output import StatOutput
output = StatOutput(options.jobfile, source)
output.xlabel = 'System Configuration'
+ output.colormap = 'RdYlGn'
if command == 'stat' or command == 'formula':
if len(args) != 1:
@@ -286,7 +287,6 @@ def commands(options, command, args):
raise CommandException
from info import ProxyGroup
- sim_seconds = source['sim_seconds']
proxy = ProxyGroup(system = source[options.system])
system = proxy.system
@@ -294,7 +294,6 @@ def commands(options, command, args):
bytes = etherdev.rxBytes + etherdev.txBytes
kbytes = bytes / 1024
packets = etherdev.rxPackets + etherdev.txPackets
- bps = etherdev.rxBandwidth + etherdev.txBandwidth
def display():
if options.graph:
@@ -337,7 +336,7 @@ def commands(options, command, args):
return
if command == 'pps':
- output.stat = packets / sim_seconds
+ output.stat = packets / source['sim_seconds']
output.ylabel = 'Packets/s'
display()
return
@@ -355,7 +354,7 @@ def commands(options, command, args):
if command == 'txbps':
output.stat = etherdev.txBandwidth / 1e9
if command == 'bps':
- output.stat = bps / 1e9
+ output.stat = (etherdev.rxBandwidth + etherdev.txBandwidth) / 1e9
output.ylabel = 'Bandwidth (Gbps)'
output.ylim = [ 0.0, 10.0 ]