summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConscript143
-rw-r--r--arch/SConscript29
-rw-r--r--arch/alpha/SConscript2
-rw-r--r--arch/alpha/arguments.cc10
-rw-r--r--arch/alpha/arguments.hh12
-rw-r--r--arch/alpha/ev5.cc15
-rw-r--r--arch/alpha/faults.cc55
-rw-r--r--arch/alpha/faults.hh117
-rw-r--r--arch/alpha/freebsd/system.cc19
-rw-r--r--arch/alpha/isa/decoder.isa2
-rw-r--r--arch/alpha/isa/main.isa22
-rw-r--r--arch/alpha/isa/mem.isa6
-rw-r--r--arch/alpha/isa_traits.hh294
-rw-r--r--arch/alpha/linux/linux.cc70
-rw-r--r--arch/alpha/linux/linux.hh128
-rw-r--r--arch/alpha/linux/process.cc44
-rw-r--r--arch/alpha/linux/process.hh8
-rw-r--r--arch/alpha/linux/system.cc48
-rw-r--r--arch/alpha/linux/system.hh1
-rw-r--r--arch/alpha/process.cc124
-rw-r--r--arch/alpha/process.hh34
-rw-r--r--arch/alpha/regfile.hh278
-rw-r--r--arch/alpha/stacktrace.cc20
-rw-r--r--arch/alpha/system.cc49
-rw-r--r--arch/alpha/system.hh1
-rw-r--r--arch/alpha/tlb.cc212
-rw-r--r--arch/alpha/tlb.hh15
-rw-r--r--arch/alpha/tru64/process.cc156
-rw-r--r--arch/alpha/tru64/process.hh7
-rw-r--r--arch/alpha/tru64/system.cc14
-rw-r--r--arch/alpha/tru64/tru64.cc70
-rw-r--r--arch/alpha/tru64/tru64.hh127
-rw-r--r--arch/alpha/types.hh64
-rw-r--r--arch/alpha/utility.hh156
-rw-r--r--arch/alpha/vtophys.cc186
-rw-r--r--arch/alpha/vtophys.hh16
-rwxr-xr-xarch/isa_parser.py180
-rw-r--r--arch/isa_specific.hh2
-rw-r--r--arch/mips/SConscript6
-rw-r--r--arch/mips/faults.cc161
-rw-r--r--arch/mips/faults.hh283
-rw-r--r--arch/mips/isa/base.isa28
-rw-r--r--arch/mips/isa/bitfields.isa6
-rw-r--r--arch/mips/isa/decoder.isa1398
-rw-r--r--arch/mips/isa/formats.isa35
-rw-r--r--arch/mips/isa/formats/branch.isa18
-rw-r--r--arch/mips/isa/formats/formats.isa35
-rw-r--r--arch/mips/isa/formats/fp.isa64
-rw-r--r--arch/mips/isa/formats/int.isa19
-rw-r--r--arch/mips/isa/formats/mem.isa26
-rw-r--r--arch/mips/isa/formats/noop.isa4
-rw-r--r--arch/mips/isa/formats/unimp.isa5
-rw-r--r--arch/mips/isa/formats/unknown.isa30
-rw-r--r--arch/mips/isa/formats/util.isa21
-rw-r--r--arch/mips/isa/includes.isa11
-rw-r--r--arch/mips/isa/main.isa12
-rw-r--r--arch/mips/isa/operands.isa34
-rw-r--r--arch/mips/isa_traits.cc362
-rw-r--r--arch/mips/isa_traits.hh527
-rw-r--r--arch/mips/linux/linux.cc70
-rw-r--r--arch/mips/linux/linux.hh124
-rw-r--r--arch/mips/linux/process.cc429
-rw-r--r--arch/mips/linux/process.hh (renamed from arch/mips/linux_process.hh)5
-rw-r--r--arch/mips/linux_process.cc588
-rw-r--r--arch/mips/process.cc125
-rw-r--r--arch/mips/process.hh35
-rw-r--r--arch/mips/regfile/float_regfile.hh159
-rw-r--r--arch/mips/regfile/int_regfile.hh73
-rw-r--r--arch/mips/regfile/misc_regfile.hh96
-rw-r--r--arch/mips/regfile/regfile.hh199
-rw-r--r--arch/mips/types.hh92
-rw-r--r--arch/mips/utility.hh41
-rw-r--r--arch/sparc/SConscript4
-rw-r--r--arch/sparc/faults.cc33
-rw-r--r--arch/sparc/faults.hh54
-rw-r--r--arch/sparc/isa/base.isa141
-rw-r--r--arch/sparc/isa/bitfields.isa14
-rw-r--r--arch/sparc/isa/decoder.isa1319
-rw-r--r--arch/sparc/isa/formats.isa27
-rw-r--r--arch/sparc/isa/formats/branch.isa264
-rw-r--r--arch/sparc/isa/formats/integerop.isa375
-rw-r--r--arch/sparc/isa/formats/mem.isa146
-rw-r--r--arch/sparc/isa/formats/noop.isa50
-rw-r--r--arch/sparc/isa/formats/nop.isa62
-rw-r--r--arch/sparc/isa/formats/priv.isa139
-rw-r--r--arch/sparc/isa/formats/trap.isa31
-rw-r--r--arch/sparc/isa/formats/unknown.isa46
-rw-r--r--arch/sparc/isa/includes.isa7
-rw-r--r--arch/sparc/isa/main.isa12
-rw-r--r--arch/sparc/isa/operands.isa98
-rw-r--r--arch/sparc/isa_traits.hh522
-rw-r--r--arch/sparc/linux/linux.cc68
-rw-r--r--arch/sparc/linux/linux.hh61
-rw-r--r--arch/sparc/linux/process.cc621
-rw-r--r--arch/sparc/linux/process.hh9
-rw-r--r--arch/sparc/process.cc345
-rw-r--r--arch/sparc/process.hh50
-rw-r--r--arch/sparc/regfile.hh812
-rw-r--r--arch/sparc/system.cc200
-rw-r--r--arch/sparc/system.hh114
-rw-r--r--arch/sparc/utility.hh89
-rw-r--r--base/chunk_generator.hh141
-rw-r--r--base/inet.hh38
-rw-r--r--base/intmath.hh4
-rw-r--r--base/loader/aout_object.cc26
-rw-r--r--base/loader/aout_object.hh2
-rw-r--r--base/loader/ecoff_object.cc26
-rw-r--r--base/loader/ecoff_object.hh2
-rw-r--r--base/loader/elf_object.cc53
-rw-r--r--base/loader/elf_object.hh5
-rw-r--r--base/loader/object_file.cc28
-rw-r--r--base/loader/object_file.hh18
-rw-r--r--base/remote_gdb.cc76
-rw-r--r--base/timebuf.hh4
-rw-r--r--base/traceflags.py2
-rw-r--r--build/SConstruct23
-rw-r--r--configs/test/SysPaths.py32
-rw-r--r--configs/test/fs.py215
-rwxr-xr-xconfigs/test/hellobin0 -> 312176 bytes
-rwxr-xr-xconfigs/test/hello_mipsbin0 -> 837626 bytes
-rwxr-xr-xconfigs/test/hello_sparcbin0 -> 644149 bytes
-rw-r--r--configs/test/test.py12
-rw-r--r--cpu/base.cc3
-rw-r--r--cpu/base.hh7
-rw-r--r--cpu/cpu_exec_context.cc92
-rw-r--r--cpu/cpu_exec_context.hh202
-rw-r--r--cpu/exec_context.hh117
-rw-r--r--cpu/exetrace.cc15
-rw-r--r--cpu/exetrace.hh2
-rw-r--r--cpu/o3/alpha_cpu.hh4
-rw-r--r--cpu/o3/alpha_cpu_impl.hh12
-rw-r--r--cpu/o3/alpha_dyn_inst.hh36
-rw-r--r--cpu/o3/cpu.cc47
-rw-r--r--cpu/o3/cpu.hh16
-rw-r--r--cpu/o3/regfile.hh80
-rw-r--r--cpu/op_class.cc50
-rw-r--r--cpu/op_class.hh (renamed from encumbered/cpu/full/op_class.hh)38
-rw-r--r--cpu/ozone/cpu.hh36
-rw-r--r--cpu/pc_event.hh5
-rw-r--r--cpu/simple/cpu.cc449
-rw-r--r--cpu/simple/cpu.hh162
-rw-r--r--cpu/static_inst.hh15
-rw-r--r--dev/alpha_console.cc166
-rw-r--r--dev/alpha_console.hh28
-rw-r--r--dev/baddev.cc67
-rw-r--r--dev/baddev.hh49
-rw-r--r--dev/etherbus.cc2
-rw-r--r--dev/etherbus.hh4
-rw-r--r--dev/etherdump.cc2
-rw-r--r--dev/etherdump.hh4
-rw-r--r--dev/etherint.hh4
-rw-r--r--dev/etherlink.cc14
-rw-r--r--dev/etherlink.hh8
-rw-r--r--dev/etherpkt.cc4
-rw-r--r--dev/etherpkt.hh12
-rw-r--r--dev/ethertap.cc8
-rw-r--r--dev/ethertap.hh6
-rw-r--r--dev/ide_ctrl.cc443
-rw-r--r--dev/ide_ctrl.hh45
-rw-r--r--dev/ide_disk.cc340
-rw-r--r--dev/ide_disk.hh21
-rw-r--r--dev/io_device.cc212
-rw-r--r--dev/io_device.hh295
-rw-r--r--dev/isa_fake.cc105
-rw-r--r--dev/isa_fake.hh35
-rw-r--r--dev/ns_gige.cc696
-rw-r--r--dev/ns_gige.hh42
-rw-r--r--dev/pciconfigall.cc166
-rw-r--r--dev/pciconfigall.hh33
-rw-r--r--dev/pcidev.cc318
-rw-r--r--dev/pcidev.hh102
-rw-r--r--dev/pktfifo.cc10
-rw-r--r--dev/pktfifo.hh12
-rw-r--r--dev/platform.cc4
-rw-r--r--dev/platform.hh7
-rw-r--r--dev/simconsole.cc1
-rw-r--r--dev/simple_disk.cc22
-rw-r--r--dev/simple_disk.hh6
-rw-r--r--dev/sinic.cc338
-rw-r--r--dev/sinic.hh44
-rw-r--r--dev/tsunami.cc13
-rw-r--r--dev/tsunami.hh6
-rw-r--r--dev/tsunami_cchip.cc532
-rw-r--r--dev/tsunami_cchip.hh52
-rw-r--r--dev/tsunami_io.cc364
-rw-r--r--dev/tsunami_io.hh58
-rw-r--r--dev/tsunami_pchip.cc386
-rw-r--r--dev/tsunami_pchip.hh61
-rw-r--r--dev/uart.cc32
-rw-r--r--dev/uart.hh26
-rw-r--r--dev/uart8250.cc127
-rw-r--r--dev/uart8250.hh24
-rw-r--r--kern/linux/events.cc2
-rw-r--r--kern/linux/linux.hh82
-rw-r--r--kern/linux/printk.cc2
-rw-r--r--kern/linux/printk.hh4
-rw-r--r--kern/system_events.cc8
-rw-r--r--kern/tru64/dump_mbuf.hh4
-rw-r--r--kern/tru64/printf.cc2
-rw-r--r--kern/tru64/printf.hh4
-rw-r--r--kern/tru64/tru64.hh222
-rw-r--r--kern/tru64/tru64_events.cc18
-rw-r--r--mem/bridge.cc263
-rw-r--r--mem/bridge.hh214
-rw-r--r--mem/bus.cc179
-rw-r--r--mem/bus.hh164
-rw-r--r--mem/mem_object.cc37
-rw-r--r--mem/mem_object.hh54
-rw-r--r--mem/packet.cc94
-rw-r--r--mem/packet.hh192
-rw-r--r--mem/page_table.cc134
-rw-r--r--mem/page_table.hh90
-rw-r--r--mem/physical.cc368
-rw-r--r--mem/physical.hh127
-rw-r--r--mem/port.cc76
-rw-r--r--mem/port.hh247
-rw-r--r--mem/request.hh202
-rw-r--r--mem/translating_port.cc186
-rw-r--r--mem/translating_port.hh64
-rw-r--r--mem/vport.cc69
-rw-r--r--mem/vport.hh76
-rw-r--r--python/m5/objects/AlphaConsole.py6
-rw-r--r--python/m5/objects/BadDevice.py4
-rw-r--r--python/m5/objects/BaseCPU.py4
-rw-r--r--python/m5/objects/Bridge.py9
-rw-r--r--python/m5/objects/Bus.py7
-rw-r--r--python/m5/objects/Device.py33
-rw-r--r--python/m5/objects/Ethernet.py6
-rw-r--r--python/m5/objects/Ide.py1
-rw-r--r--python/m5/objects/MemObject.py5
-rw-r--r--python/m5/objects/Pci.py6
-rw-r--r--python/m5/objects/PhysicalMemory.py6
-rw-r--r--python/m5/objects/Process.py10
-rw-r--r--python/m5/objects/Root.py4
-rw-r--r--python/m5/objects/SimpleDisk.py2
-rw-r--r--python/m5/objects/System.py18
-rw-r--r--python/m5/objects/Tsunami.py14
-rw-r--r--python/m5/objects/Uart.py7
-rw-r--r--sim/byteswap.hh21
-rw-r--r--sim/faults.cc1
-rw-r--r--sim/host.hh2
-rw-r--r--sim/main.cc4
-rw-r--r--sim/process.cc214
-rw-r--r--sim/process.hh87
-rw-r--r--sim/pseudo_inst.cc2
-rw-r--r--sim/sim_object.cc27
-rw-r--r--sim/sim_object.hh11
-rw-r--r--sim/syscall_emul.cc45
-rw-r--r--sim/syscall_emul.hh101
-rw-r--r--sim/system.cc106
-rw-r--r--sim/system.hh53
-rw-r--r--sim/vptr.hh12
-rwxr-xr-xutil/qdo4
253 files changed, 16349 insertions, 8688 deletions
diff --git a/SConscript b/SConscript
index 8f2ae761d..a2d5de279 100644
--- a/SConscript
+++ b/SConscript
@@ -62,6 +62,7 @@ base_sources = Split('''
base/range.cc
base/random.cc
base/sat_counter.cc
+ base/serializer.cc
base/socket.cc
base/statistics.cc
base/str.cc
@@ -81,70 +82,21 @@ base_sources = Split('''
base/stats/text.cc
cpu/base.cc
- cpu/base_dyn_inst.cc
cpu/cpu_exec_context.cc
cpu/exetrace.cc
+ cpu/op_class.cc
cpu/pc_event.cc
cpu/static_inst.cc
cpu/sampler/sampler.cc
- cpu/trace/reader/mem_trace_reader.cc
- cpu/trace/reader/ibm_reader.cc
- cpu/trace/reader/itx_reader.cc
- cpu/trace/reader/m5_reader.cc
- cpu/trace/opt_cpu.cc
- cpu/trace/trace_cpu.cc
-
- encumbered/mem/functional/main.cc
-
- mem/base_hier.cc
- mem/base_mem.cc
- mem/hier_params.cc
- mem/mem_cmd.cc
- mem/mem_debug.cc
- mem/mem_req.cc
- mem/memory_interface.cc
- mem/bus/base_interface.cc
- mem/bus/bus.cc
- mem/bus/bus_bridge.cc
- mem/bus/bus_bridge_master.cc
- mem/bus/bus_bridge_slave.cc
- mem/bus/bus_interface.cc
- mem/bus/dma_bus_interface.cc
- mem/bus/dma_interface.cc
- mem/bus/master_interface.cc
- mem/bus/slave_interface.cc
- mem/cache/base_cache.cc
- mem/cache/cache.cc
- mem/cache/cache_builder.cc
- mem/cache/coherence/coherence_protocol.cc
- mem/cache/coherence/uni_coherence.cc
- mem/cache/miss/blocking_buffer.cc
- mem/cache/miss/miss_queue.cc
- mem/cache/miss/mshr.cc
- mem/cache/miss/mshr_queue.cc
- mem/cache/prefetch/base_prefetcher.cc
- mem/cache/prefetch/prefetcher.cc
- mem/cache/prefetch/tagged_prefetcher.cc
- mem/cache/tags/base_tags.cc
- mem/cache/tags/cache_tags.cc
- mem/cache/tags/fa_lru.cc
- mem/cache/tags/iic.cc
- mem/cache/tags/lru.cc
- mem/cache/tags/repl/gen.cc
- mem/cache/tags/repl/repl.cc
- mem/cache/tags/split.cc
- mem/cache/tags/split_lru.cc
- mem/cache/tags/split_lifo.cc
- mem/functional/functional.cc
- mem/timing/base_memory.cc
- mem/timing/dram_memory.cc
- mem/timing/dram_mem_bank.cc
- mem/timing/dram_memory_builder.cc
- mem/timing/memory_builder.cc
- mem/timing/simple_mem_bank.cc
- mem/trace/itx_writer.cc
- mem/trace/mem_trace_writer.cc
- mem/trace/m5_writer.cc
+
+ mem/bridge.cc
+ mem/bus.cc
+ mem/connector.cc
+ mem/mem_object.cc
+ mem/packet.cc
+ mem/physical.cc
+ mem/port.cc
+ mem/request.cc
python/pyconfig.cc
python/embedded_py.cc
@@ -165,6 +117,7 @@ base_sources = Split('''
sim/startup.cc
sim/stat_context.cc
sim/stat_control.cc
+ sim/system.cc
sim/trace_context.cc
''')
@@ -207,6 +160,17 @@ full_cpu_sources = Split('''
encumbered/cpu/full/iq/standard/iq_standard.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
@@ -224,30 +188,32 @@ full_system_sources = Split('''
dev/alpha_console.cc
dev/baddev.cc
- dev/simconsole.cc
dev/disk_image.cc
dev/etherbus.cc
dev/etherdump.cc
dev/etherint.cc
dev/etherlink.cc
dev/etherpkt.cc
- dev/ethertap.cc
- dev/ide_ctrl.cc
+ dev/ethertap.cc
+ dev/ide_ctrl.cc
dev/ide_disk.cc
dev/io_device.cc
+ dev/isa_fake.cc
dev/ns_gige.cc
dev/pciconfigall.cc
dev/pcidev.cc
dev/pcifake.cc
dev/pktfifo.cc
dev/platform.cc
- dev/sinic.cc
+ dev/simconsole.cc
dev/simple_disk.cc
+ dev/sinic.cc
dev/tsunami.cc
dev/tsunami_cchip.cc
- dev/isa_fake.cc
dev/tsunami_io.cc
+ dev/tsunami_fake.cc
dev/tsunami_pchip.cc
+
dev/uart.cc
dev/uart8250.cc
@@ -257,16 +223,19 @@ full_system_sources = Split('''
kern/linux/events.cc
kern/linux/linux_syscalls.cc
kern/linux/printk.cc
+
+ mem/vport.cc
+
+ sim/pseudo_inst.cc
+ ''')
+
+
+if env['TARGET_ISA'] == 'alpha':
+ full_system_sources += Split('''
kern/tru64/dump_mbuf.cc
kern/tru64/printf.cc
kern/tru64/tru64_events.cc
kern/tru64/tru64_syscalls.cc
-
- mem/functional/memory_control.cc
- mem/functional/physical.cc
-
- sim/system.cc
- sim/pseudo_inst.cc
''')
# turbolaser encumbered sources
@@ -291,16 +260,30 @@ turbolaser_sources = Split('''
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
- cpu/memtest/memtest.cc
- encumbered/eio/eio.cc
- encumbered/eio/exolex.cc
- encumbered/eio/libexo.cc
- kern/linux/linux.cc
- kern/tru64/tru64.cc
+ mem/translating_port.cc
+ mem/page_table.cc
sim/process.cc
sim/syscall_emul.cc
''')
+#if env['TARGET_ISA'] == 'alpha':
+# syscall_emulation_sources += Split('''
+# kern/tru64/tru64.cc
+# ''')
+
+alpha_eio_sources = Split('''
+ encumbered/eio/exolex.cc
+ encumbered/eio/libexo.cc
+ encumbered/eio/eio.cc
+ ''')
+
+if env['TARGET_ISA'] == 'ALPHA_ISA':
+ syscall_emulation_sources += alpha_eio_sources
+
+memtest_sources = Split('''
+ cpu/memtest/memtest.cc
+ ''')
+
# Add a flag defining what THE_ISA should be for all compilation
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
@@ -380,7 +363,7 @@ env.Append(CPPPATH='./libelf')
# Debug binary
debugEnv = env.Copy(OBJSUFFIX='.do')
debugEnv.Label = 'debug'
-debugEnv.Append(CCFLAGS=Split('-g -gstabs+ -O0'))
+debugEnv.Append(CCFLAGS=Split('-g3 -gdwarf-2 -O0'))
debugEnv.Append(CPPDEFINES='DEBUG')
tlist = debugEnv.Program(target = 'm5.debug',
source = make_objs(sources, debugEnv))
@@ -389,7 +372,7 @@ debugEnv.M5Binary = tlist[0]
# Optimized binary
optEnv = env.Copy()
optEnv.Label = 'opt'
-optEnv.Append(CCFLAGS=Split('-g -O5'))
+optEnv.Append(CCFLAGS=Split('-g -O3'))
tlist = optEnv.Program(target = 'm5.opt',
source = make_objs(sources, optEnv))
optEnv.M5Binary = tlist[0]
@@ -397,7 +380,7 @@ optEnv.M5Binary = tlist[0]
# "Fast" binary
fastEnv = env.Copy(OBJSUFFIX='.fo')
fastEnv.Label = 'fast'
-fastEnv.Append(CCFLAGS=Split('-O5'))
+fastEnv.Append(CCFLAGS=Split('-O3'))
fastEnv.Append(CPPDEFINES='NDEBUG')
fastEnv.Program(target = 'm5.fast.unstripped',
source = make_objs(sources, fastEnv))
@@ -409,7 +392,7 @@ fastEnv.M5Binary = tlist[0]
# Profiled binary
profEnv = env.Copy(OBJSUFFIX='.po')
profEnv.Label = 'prof'
-profEnv.Append(CCFLAGS=Split('-O5 -g -pg'), LINKFLAGS='-pg')
+profEnv.Append(CCFLAGS=Split('-O3 -g -pg'), LINKFLAGS='-pg')
tlist = profEnv.Program(target = 'm5.prof',
source = make_objs(sources, profEnv))
profEnv.M5Binary = tlist[0]
diff --git a/arch/SConscript b/arch/SConscript
index 0533261a2..99c861568 100644
--- a/arch/SConscript
+++ b/arch/SConscript
@@ -45,13 +45,17 @@ sources = []
# List of headers to generate
isa_switch_hdrs = Split('''
+ arguments.hh
+ constants.hh
+ faults.hh
isa_traits.hh
- tlb.hh
process.hh
- arguments.hh
+ regfile.hh
stacktrace.hh
+ tlb.hh
+ types.hh
+ utility.hh
vtophys.hh
- faults.hh
''')
# Generate the header. target[0] is the full path of the output
@@ -96,18 +100,12 @@ for hdr in isa_switch_hdrs:
#
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('.'))
+isa_scanner = SCons.Scanner.Classic("ISAScan",
+ [".isa", ".ISA"],
+ "SRCDIR",
+ r'^\s*##include\s+"([\w/.-]*)"')
-iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"],
- path_function = ISAPath)
-env.Append(SCANNERS = iscan)
+env.Append(SCANNERS = isa_scanner)
#
# Now create a Builder object that uses isa_parser.py to generate C++
@@ -134,8 +132,7 @@ 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,
+isa_desc_builder = Builder(action='python $SOURCES $TARGET.dir $CPU_MODELS',
emitter = isa_desc_emitter)
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript
index ed7fd3404..1b20f8b1f 100644
--- a/arch/alpha/SConscript
+++ b/arch/alpha/SConscript
@@ -65,7 +65,9 @@ full_system_sources = Split('''
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
+ linux/linux.cc
linux/process.cc
+ tru64/tru64.cc
tru64/process.cc
process.cc
''')
diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc
index 019390aeb..adc371682 100644
--- a/arch/alpha/arguments.cc
+++ b/arch/alpha/arguments.cc
@@ -29,7 +29,7 @@
#include "arch/alpha/arguments.hh"
#include "arch/alpha/vtophys.hh"
#include "cpu/exec_context.hh"
-#include "mem/functional/physical.hh"
+#include "mem/vport.hh"
using namespace AlphaISA;
@@ -54,13 +54,15 @@ AlphaArguments::getArg(bool fp)
{
if (number < 6) {
if (fp)
- return xc->readFloatRegInt(16 + number);
+ return xc->readFloatRegBits(16 + number);
else
return xc->readIntReg(16 + number);
} else {
Addr sp = xc->readIntReg(30);
- Addr paddr = vtophys(xc, sp + (number-6) * sizeof(uint64_t));
- return xc->getPhysMemPtr()->phys_read_qword(paddr);
+ VirtualPort *vp = xc->getVirtPort(xc);
+ uint64_t arg = vp->read<uint64_t>(sp + (number-6) * sizeof(uint64_t));
+ xc->delVirtPort(vp);
+ return arg;
}
}
diff --git a/arch/alpha/arguments.hh b/arch/alpha/arguments.hh
index 75346bf58..bd1c6cb1d 100644
--- a/arch/alpha/arguments.hh
+++ b/arch/alpha/arguments.hh
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __ARGUMENTS_HH__
-#define __ARGUMENTS_HH__
+#ifndef __ARCH_ALPHA_ARGUMENTS_HH__
+#define __ARCH_ALPHA_ARGUMENTS_HH__
#include <assert.h>
@@ -37,6 +37,8 @@
class ExecContext;
+namespace AlphaISA {
+
class AlphaArguments
{
protected:
@@ -135,9 +137,11 @@ class AlphaArguments
operator char *() {
char *buf = data->alloc(2048);
- CopyString(xc, buf, getArg(), 2048);
+ CopyStringOut(xc, buf, getArg(), 2048);
return buf;
}
};
-#endif // __ARGUMENTS_HH__
+}; // namespace AlphaISA
+
+#endif // __ARCH_ALPHA_ARGUMENTS_HH__
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 019e83dd4..12f7659e6 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -36,7 +36,6 @@
#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"
#include "sim/debug.hh"
#include "sim/sim_events.hh"
@@ -134,7 +133,7 @@ AlphaISA::zeroRegisters(CPU *cpu)
// (no longer very clean due to the change in setIntReg() in the
// cpu model. Consider changing later.)
cpu->cpuXC->setIntReg(ZeroReg, 0);
- cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0);
+ cpu->cpuXC->setFloatReg(ZeroReg, 0.0);
}
Fault
@@ -542,10 +541,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc)
}
void
-AlphaISA::MiscRegFile::copyIprs(ExecContext *xc)
+AlphaISA::copyIprs(ExecContext *src, ExecContext *dest)
{
for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) {
- ipr[i] = xc->readMiscReg(i);
+ dest->setMiscReg(i, src->readMiscReg(i));
}
}
@@ -575,12 +574,4 @@ CPUExecContext::simPalCheck(int palFunc)
return true;
}
-//Forward instantiation for FastCPU object
-template
-void AlphaISA::processInterrupts(FastCPU *xc);
-
-//Forward instantiation for FastCPU object
-template
-void AlphaISA::zeroRegisters(FastCPU *xc);
-
#endif // FULL_SYSTEM
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc
index e0918da21..c8cb9124e 100644
--- a/arch/alpha/faults.cc
+++ b/arch/alpha/faults.cc
@@ -30,6 +30,9 @@
#include "cpu/exec_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
+#if FULL_SYSTEM
+#include "arch/alpha/ev5.hh"
+#endif
namespace AlphaISA
{
@@ -70,6 +73,10 @@ FaultName DtbAcvFault::_name = "dfault";
FaultVect DtbAcvFault::_vect = 0x0381;
FaultStat DtbAcvFault::_count;
+FaultName DtbAlignmentFault::_name = "unalign";
+FaultVect DtbAlignmentFault::_vect = 0x0301;
+FaultStat DtbAlignmentFault::_count;
+
FaultName ItbMissFault::_name = "itbmiss";
FaultVect ItbMissFault::_vect = 0x0181;
FaultStat ItbMissFault::_count;
@@ -98,6 +105,10 @@ FaultName IntegerOverflowFault::_name = "intover";
FaultVect IntegerOverflowFault::_vect = 0x0501;
FaultStat IntegerOverflowFault::_count;
+FaultName UnimpFault::_name = "Unimplemented Simulator feature";
+FaultVect UnimpFault::_vect = 0x0001;
+FaultStat UnimpFault::_count;
+
#if FULL_SYSTEM
void AlphaFault::invoke(ExecContext * xc)
@@ -125,6 +136,50 @@ void ArithmeticFault::invoke(ExecContext * xc)
panic("Arithmetic traps are unimplemented!");
}
+void DtbFault::invoke(ExecContext * xc)
+{
+ // Set fault address and flags. Even though we're modeling an
+ // EV5, we use the EV6 technique of not latching fault registers
+ // on VPTE loads (instead of locking the registers until IPR_VA is
+ // read, like the EV5). The EV6 approach is cleaner and seems to
+ // work with EV5 PAL code, but not the other way around.
+ if (!xc->misspeculating()
+ && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) {
+ // set VA register with faulting address
+ xc->setMiscReg(AlphaISA::IPR_VA, vaddr);
+
+ // set MM_STAT register flags
+ xc->setMiscReg(AlphaISA::IPR_MM_STAT,
+ (((EV5::Opcode(xc->getInst()) & 0x3f) << 11)
+ | ((EV5::Ra(xc->getInst()) & 0x1f) << 6)
+ | (flags & 0x3f)));
+
+ // set VA_FORM register with faulting formatted address
+ xc->setMiscReg(AlphaISA::IPR_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
+ }
+
+ AlphaFault::invoke(xc);
+}
+
+void ItbFault::invoke(ExecContext * xc)
+{
+ if (!xc->misspeculating()) {
+ xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
+ xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
+ (AlphaISA::VAddr(pc).vpn() << 3));
+ }
+
+ AlphaFault::invoke(xc);
+}
+
+void UnimpFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ panic("Unimpfault: %s\n", panicStr.c_str());
+}
+
#endif
} // namespace AlphaISA
diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh
index 1a196cc94..5024c124b 100644
--- a/arch/alpha/faults.hh
+++ b/arch/alpha/faults.hh
@@ -29,6 +29,7 @@
#ifndef __ALPHA_FAULTS_HH__
#define __ALPHA_FAULTS_HH__
+#include "arch/alpha/isa_traits.hh"
#include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
@@ -130,85 +131,167 @@ class InterruptFault : public AlphaFault
FaultStat & countStat() {return _count;}
};
-class NDtbMissFault : public AlphaFault
+class DtbFault : public AlphaFault
+{
+#if FULL_SYSTEM
+ private:
+ AlphaISA::VAddr vaddr;
+ uint32_t reqFlags;
+ uint64_t flags;
+ public:
+ DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags)
+ : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags)
+ { }
+#endif
+ FaultName name() = 0;
+ FaultVect vect() = 0;
+ FaultStat & countStat() = 0;
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class NDtbMissFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class PDtbMissFault : public AlphaFault
+class PDtbMissFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbPageFault : public DtbFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+#if FULL_SYSTEM
+ DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class DtbPageFault : public AlphaFault
+class DtbAcvFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class DtbAcvFault : public AlphaFault
+class DtbAlignmentFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class ItbMissFault : public AlphaFault
+class ItbFault : public AlphaFault
+{
+ private:
+ Addr pc;
+ public:
+ ItbFault(Addr _pc)
+ : pc(_pc)
+ { }
+ FaultName name() = 0;
+ FaultVect vect() = 0;
+ FaultStat & countStat() = 0;
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class ItbMissFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+ ItbMissFault(Addr pc)
+ : ItbFault(pc)
+ { }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class ItbPageFault : public AlphaFault
+class ItbPageFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+ ItbPageFault(Addr pc)
+ : ItbFault(pc)
+ { }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class ItbAcvFault : public AlphaFault
+class ItbAcvFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+ ItbAcvFault(Addr pc)
+ : ItbFault(pc)
+ { }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
@@ -264,6 +347,26 @@ class IntegerOverflowFault : public AlphaFault
FaultStat & countStat() {return _count;}
};
+class UnimpFault : public AlphaFault
+{
+ private:
+ std::string panicStr;
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ UnimpFault(std::string _str)
+ : panicStr(_str)
+ { }
+
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
} // AlphaISA namespace
#endif // __FAULTS_HH__
diff --git a/arch/alpha/freebsd/system.cc b/arch/alpha/freebsd/system.cc
index e32053afd..3e50fb9a5 100644
--- a/arch/alpha/freebsd/system.cc
+++ b/arch/alpha/freebsd/system.cc
@@ -37,8 +37,8 @@
#include "arch/alpha/freebsd/system.hh"
#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
#include "arch/isa_traits.hh"
#include "sim/builder.hh"
#include "sim/byteswap.hh"
@@ -74,20 +74,12 @@ FreebsdAlphaSystem::doCalibrateClocks(ExecContext *xc)
{
Addr ppc_vaddr = 0;
Addr timer_vaddr = 0;
- Addr ppc_paddr = 0;
- Addr timer_paddr = 0;
ppc_vaddr = (Addr)xc->readIntReg(ArgumentReg1);
timer_vaddr = (Addr)xc->readIntReg(ArgumentReg2);
- ppc_paddr = vtophys(physmem, ppc_vaddr);
- timer_paddr = vtophys(physmem, timer_vaddr);
-
- uint8_t *ppc = physmem->dma_addr(ppc_paddr, sizeof(uint32_t));
- uint8_t *timer = physmem->dma_addr(timer_paddr, sizeof(uint32_t));
-
- *(uint32_t *)ppc = htog((uint32_t)Clock::Frequency);
- *(uint32_t *)timer = htog((uint32_t)TIMER_FREQUENCY);
+ virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency);
+ virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY);
}
@@ -102,7 +94,6 @@ FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
SimObjectParam<PhysicalMemory *> physmem;
Param<string> kernel;
@@ -125,7 +116,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
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"),
@@ -147,7 +137,6 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem)
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;
diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa
index f46e32fd1..1adcfb948 100644
--- a/arch/alpha/isa/decoder.isa
+++ b/arch/alpha/isa/decoder.isa
@@ -693,7 +693,7 @@ decode OPCODE default Unknown::unknown() {
SimExit(curTick, "halt instruction encountered");
}}, IsNonSpeculative);
0x83: callsys({{
- xc->syscall();
+ xc->syscall(R0);
}}, IsNonSpeculative);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }});
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
index 17c9989ab..746fe776d 100644
--- a/arch/alpha/isa/main.isa
+++ b/arch/alpha/isa/main.isa
@@ -34,7 +34,7 @@ output header {{
#include "config/ss_compatible_fp.hh"
#include "cpu/static_inst.hh"
#include "arch/alpha/faults.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
+#include "mem/request.hh" // some constructors use MemReq flags
}};
output decoder {{
@@ -418,31 +418,31 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
}};
// Integer instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/int.isa"
+##include "int.isa"
// Floating-point instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/fp.isa"
+##include "fp.isa"
// Memory instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/mem.isa"
+##include "mem.isa"
// Branch/jump instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/branch.isa"
+##include "branch.isa"
// PAL instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/pal.isa"
+##include "pal.isa"
// Opcdec fault instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/opcdec.isa"
+##include "opcdec.isa"
// Unimplemented instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/unimp.isa"
+##include "unimp.isa"
// Unknown instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/unknown.isa"
+##include "unknown.isa"
// Execution utility functions
-##include "m5/arch/alpha/isa/util.isa"
+##include "util.isa"
// The actual decoder
-##include "m5/arch/alpha/isa/decoder.isa"
+##include "decoder.isa"
diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa
index 3c8b4f755..8742d308f 100644
--- a/arch/alpha/isa/mem.isa
+++ b/arch/alpha/isa/mem.isa
@@ -311,8 +311,7 @@ def template LoadCompleteAcc {{
Fault fault = NoFault;
%(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
+ %(op_decl)s;
memcpy(&Mem, data, sizeof(Mem));
@@ -410,8 +409,7 @@ def template StoreInitiateAcc {{
uint64_t write_result = 0;
%(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
+ %(op_decl)s;
%(op_rd)s;
%(ea_code)s;
diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh
index 878193881..65c72115b 100644
--- a/arch/alpha/isa_traits.hh
+++ b/arch/alpha/isa_traits.hh
@@ -30,29 +30,15 @@
#define __ARCH_ALPHA_ISA_TRAITS_HH__
namespace LittleEndianGuest {}
-using namespace LittleEndianGuest;
-//#include "arch/alpha/faults.hh"
-#include "base/misc.hh"
+#include "arch/alpha/types.hh"
+#include "arch/alpha/constants.hh"
+#include "arch/alpha/regfile.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
-class StaticInst;
class StaticInstPtr;
-namespace EV5 {
-int DTB_ASN_ASN(uint64_t reg);
-int ITB_ASN_ASN(uint64_t reg);
-}
-
#if !FULL_SYSTEM
class SyscallReturn {
public:
@@ -89,261 +75,21 @@ class SyscallReturn {
#endif
+#if FULL_SYSTEM
+#include "arch/alpha/isa_fullsys_traits.hh"
+#endif
namespace AlphaISA
{
- typedef uint32_t MachInst;
- typedef uint64_t ExtMachInst;
- typedef uint8_t RegIndex;
-
- 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 = 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;
- 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;
-
-extern const Addr PageShift;
-extern const Addr PageBytes;
-extern const Addr PageMask;
-extern const Addr PageOffset;
+using namespace LittleEndianGuest;
// 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;
- 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
-
- 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
-
- private:
- MiscReg readIpr(int idx, Fault &fault, ExecContext *xc);
-
- Fault setIpr(int idx, uint64_t val, ExecContext *xc);
-
- void copyIprs(ExecContext *xc);
-#endif
- friend class RegFile;
- };
-
- const int TotalNumRegs = NumIntRegs + NumFloatRegs +
- NumMiscRegs + NumInternalProcRegs;
-
- const int 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;
-
-#if FULL_SYSTEM
- int intrflag; // interrupt flag
- 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 inline ExtMachInst makeExtMI(MachInst inst, const uint64_t &pc);
-
StaticInstPtr decodeInst(ExtMachInst);
- // return a no-op instruction... used for instruction fetch faults
- extern const ExtMachInst NoopMachInst;
-
- enum annotes {
- ANNOTE_NONE = 0,
- // An impossible number for instruction annotations
- ITOUCH_ANNOTE = 0xffffffff,
- };
-
- 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
static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
{
@@ -352,33 +98,15 @@ extern const int reg_redir[NumIntRegs];
// 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();
+ regs->setIntReg(SyscallSuccessReg, 0);
+ regs->setIntReg(ReturnValueReg, return_value.value());
} else {
// got an error, return details
- regs->intRegFile[SyscallSuccessReg] = (IntReg) -1;
- regs->intRegFile[ReturnValueReg] = -return_value.value();
+ regs->setIntReg(SyscallSuccessReg, (IntReg)-1);
+ regs->setIntReg(ReturnValueReg, -return_value.value());
}
}
#endif
};
-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
-
-#include "arch/alpha/ev5.hh"
-#endif
-
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
diff --git a/arch/alpha/linux/linux.cc b/arch/alpha/linux/linux.cc
new file mode 100644
index 000000000..f123ae1fe
--- /dev/null
+++ b/arch/alpha/linux/linux.cc
@@ -0,0 +1,70 @@
+/*
+ * 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/linux.hh"
+
+// open(2) flags translation table
+OpenFlagTransTable AlphaLinux::openFlagTable[] = {
+#ifdef _MSC_VER
+ { AlphaLinux::TGT_O_RDONLY, _O_RDONLY },
+ { AlphaLinux::TGT_O_WRONLY, _O_WRONLY },
+ { AlphaLinux::TGT_O_RDWR, _O_RDWR },
+ { AlphaLinux::TGT_O_APPEND, _O_APPEND },
+ { AlphaLinux::TGT_O_CREAT, _O_CREAT },
+ { AlphaLinux::TGT_O_TRUNC, _O_TRUNC },
+ { AlphaLinux::TGT_O_EXCL, _O_EXCL },
+#ifdef _O_NONBLOCK
+ { AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+ { AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+ { AlphaLinux::TGT_O_SYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+ { AlphaLinux::TGT_O_RDONLY, O_RDONLY },
+ { AlphaLinux::TGT_O_WRONLY, O_WRONLY },
+ { AlphaLinux::TGT_O_RDWR, O_RDWR },
+ { AlphaLinux::TGT_O_APPEND, O_APPEND },
+ { AlphaLinux::TGT_O_CREAT, O_CREAT },
+ { AlphaLinux::TGT_O_TRUNC, O_TRUNC },
+ { AlphaLinux::TGT_O_EXCL, O_EXCL },
+ { AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK },
+ { AlphaLinux::TGT_O_NOCTTY, O_NOCTTY },
+#ifdef O_SYNC
+ { AlphaLinux::TGT_O_SYNC, O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int AlphaLinux::NUM_OPEN_FLAGS =
+ (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0]));
+
+
+
diff --git a/arch/alpha/linux/linux.hh b/arch/alpha/linux/linux.hh
new file mode 100644
index 000000000..f04e2bfa8
--- /dev/null
+++ b/arch/alpha/linux/linux.hh
@@ -0,0 +1,128 @@
+/*
+ * 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_ALPHA_LINUX_HH
+#define __ALPHA_ALPHA_LINUX_HH
+
+#include "kern/linux/linux.hh"
+
+/* AlphaLinux class contains static constants/definitions/misc.
+ * structures which are specific to the Linux OS AND the Alpha
+ * architecture
+ */
+class AlphaLinux : public Linux
+{
+ public:
+
+ /// 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;
+
+ //@{
+ /// 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
+ //@}
+
+ /// 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
+ static const unsigned GSI_IEEE_FP_CONTROL = 45;
+ //@}
+
+ //@{
+ /// For getrusage().
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
+ static const int TGT_RUSAGE_BOTH = -2;
+ //@}
+
+ //@{
+ /// For setsysinfo().
+ static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
+ //@}
+
+ //@{
+ /// 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;
+ //@}
+
+ /// For table().
+ static const int TBL_SYSINFO = 12;
+
+ /// 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
+ };
+};
+
+#endif
diff --git a/arch/alpha/linux/process.cc b/arch/alpha/linux/process.cc
index 1c911bc50..9f4f65db8 100644
--- a/arch/alpha/linux/process.cc
+++ b/arch/alpha/linux/process.cc
@@ -26,13 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/linux/linux.hh"
#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"
@@ -55,7 +55,7 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process,
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "alpha");
- name.copyOut(xc->getMemPtr());
+ name.copyOut(xc->getMemPort());
return 0;
}
@@ -75,7 +75,7 @@ osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
// I don't think this exactly matches the HW FPCR
*fpcr = 0;
- fpcr.copyOut(xc->getMemPtr());
+ fpcr.copyOut(xc->getMemPort());
return 0;
}
@@ -101,7 +101,7 @@ osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
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());
+ fpcr.copyIn(xc->getMemPort());
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
return 0;
@@ -133,7 +133,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 12 */ SyscallDesc("chdir", unimplementedFunc),
/* 13 */ SyscallDesc("fchdir", unimplementedFunc),
/* 14 */ SyscallDesc("mknod", unimplementedFunc),
- /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>),
+ /* 15 */ SyscallDesc("chmod", chmodFunc<AlphaLinux>),
/* 16 */ SyscallDesc("chown", chownFunc),
/* 17 */ SyscallDesc("brk", obreakFunc),
/* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
@@ -163,7 +163,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 42 */ SyscallDesc("pipe", pipePseudoFunc),
/* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
/* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
- /* 45 */ SyscallDesc("open", openFunc<Linux>),
+ /* 45 */ SyscallDesc("open", openFunc<AlphaLinux>),
/* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
/* 47 */ SyscallDesc("getxgid", getgidPseudoFunc),
/* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
@@ -172,7 +172,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 51 */ SyscallDesc("acct", unimplementedFunc),
/* 52 */ SyscallDesc("sigpending", unimplementedFunc),
/* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc),
- /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<AlphaLinux>),
/* 55 */ SyscallDesc("osf_reboot", unimplementedFunc),
/* 56 */ SyscallDesc("osf_revoke", unimplementedFunc),
/* 57 */ SyscallDesc("symlink", unimplementedFunc),
@@ -185,11 +185,11 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
/* 65 */ SyscallDesc("osf_mremap", unimplementedFunc),
/* 66 */ SyscallDesc("vfork", unimplementedFunc),
- /* 67 */ SyscallDesc("stat", statFunc<Linux>),
- /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>),
+ /* 67 */ SyscallDesc("stat", statFunc<AlphaLinux>),
+ /* 68 */ SyscallDesc("lstat", lstatFunc<AlphaLinux>),
/* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc),
/* 70 */ SyscallDesc("osf_sstk", unimplementedFunc),
- /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<AlphaLinux>),
/* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc),
/* 73 */ SyscallDesc("munmap", munmapFunc),
/* 74 */ SyscallDesc("mprotect", ignoreFunc),
@@ -209,7 +209,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 88 */ SyscallDesc("sethostname", unimplementedFunc),
/* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
/* 90 */ SyscallDesc("dup2", unimplementedFunc),
- /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>),
+ /* 91 */ SyscallDesc("fstat", fstatFunc<AlphaLinux>),
/* 92 */ SyscallDesc("fcntl", fcntlFunc),
/* 93 */ SyscallDesc("osf_select", unimplementedFunc),
/* 94 */ SyscallDesc("poll", unimplementedFunc),
@@ -239,10 +239,10 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
/* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
/* 120 */ SyscallDesc("readv", unimplementedFunc),
- /* 121 */ SyscallDesc("writev", writevFunc<Linux>),
+ /* 121 */ SyscallDesc("writev", writevFunc<AlphaLinux>),
/* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc),
/* 123 */ SyscallDesc("fchown", fchownFunc),
- /* 124 */ SyscallDesc("fchmod", fchmodFunc<Linux>),
+ /* 124 */ SyscallDesc("fchmod", fchmodFunc<AlphaLinux>),
/* 125 */ SyscallDesc("recvfrom", unimplementedFunc),
/* 126 */ SyscallDesc("setreuid", unimplementedFunc),
/* 127 */ SyscallDesc("setregid", unimplementedFunc),
@@ -262,7 +262,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 141 */ SyscallDesc("getpeername", unimplementedFunc),
/* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc),
/* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc),
- /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>),
+ /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<AlphaLinux>),
/* 145 */ SyscallDesc("setrlimit", ignoreFunc),
/* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc),
/* 147 */ SyscallDesc("setsid", unimplementedFunc),
@@ -480,12 +480,12 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
/* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
/* 358 */ SyscallDesc("select", unimplementedFunc),
- /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>),
+ /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<AlphaLinux>),
/* 360 */ SyscallDesc("settimeofday", unimplementedFunc),
/* 361 */ SyscallDesc("getitimer", unimplementedFunc),
/* 362 */ SyscallDesc("setitimer", unimplementedFunc),
- /* 363 */ SyscallDesc("utimes", utimesFunc<Linux>),
- /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>),
+ /* 363 */ SyscallDesc("utimes", utimesFunc<AlphaLinux>),
+ /* 364 */ SyscallDesc("getrusage", getrusageFunc<AlphaLinux>),
/* 365 */ SyscallDesc("wait4", unimplementedFunc),
/* 366 */ SyscallDesc("adjtimex", unimplementedFunc),
/* 367 */ SyscallDesc("getcwd", unimplementedFunc),
@@ -547,8 +547,8 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 423 */ SyscallDesc("semtimedop", unimplementedFunc),
/* 424 */ SyscallDesc("tgkill", unimplementedFunc),
/* 425 */ SyscallDesc("stat64", unimplementedFunc),
- /* 426 */ SyscallDesc("lstat64", lstat64Func<Linux>),
- /* 427 */ SyscallDesc("fstat64", fstat64Func<Linux>),
+ /* 426 */ SyscallDesc("lstat64", lstat64Func<AlphaLinux>),
+ /* 427 */ SyscallDesc("fstat64", fstat64Func<AlphaLinux>),
/* 428 */ SyscallDesc("vserver", unimplementedFunc),
/* 429 */ SyscallDesc("mbind", unimplementedFunc),
/* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc),
@@ -567,15 +567,17 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
AlphaLinuxProcess::AlphaLinuxProcess(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, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ : AlphaLiveProcess(name, objFile, system, stdin_fd, stdout_fd,
+ stderr_fd, argv, envp),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{
- init_regs->intRegFile[0] = 0;
+ //init_regs->intRegFile[0] = 0;
}
diff --git a/arch/alpha/linux/process.hh b/arch/alpha/linux/process.hh
index 7de1b1ac1..2e0566665 100644
--- a/arch/alpha/linux/process.hh
+++ b/arch/alpha/linux/process.hh
@@ -29,16 +29,18 @@
#ifndef __ALPHA_LINUX_PROCESS_HH__
#define __ALPHA_LINUX_PROCESS_HH__
-#include "sim/process.hh"
+#include "arch/alpha/process.hh"
+namespace AlphaISA {
/// A process with emulated Alpha/Linux syscalls.
-class AlphaLinuxProcess : public LiveProcess
+class AlphaLinuxProcess : public AlphaLiveProcess
{
public:
/// Constructor.
AlphaLinuxProcess(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);
@@ -54,5 +56,5 @@ class AlphaLinuxProcess : public LiveProcess
const int Num_Syscall_Descs;
};
-
+} // namespace AlphaISA
#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/arch/alpha/linux/system.cc b/arch/alpha/linux/system.cc
index f9275d15e..cdb96096c 100644
--- a/arch/alpha/linux/system.cc
+++ b/arch/alpha/linux/system.cc
@@ -46,8 +46,8 @@
#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 "mem/physical.hh"
+#include "mem/port.hh"
#include "sim/builder.hh"
#include "sim/byteswap.hh"
@@ -59,7 +59,6 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
: AlphaSystem(p)
{
Addr addr = 0;
- Addr paddr = 0;
/**
* The symbol swapper_pg_dir marks the beginning of the kernel and
@@ -73,25 +72,17 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
* Since we aren't using a bootloader, we have to copy the
* kernel arguments directly into the kernel's memory.
*/
- paddr = vtophys(physmem, CommandLine());
- char *commandline = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
- if (commandline)
- strncpy(commandline, params()->boot_osflags.c_str(), CommandLineSize);
+ virtPort.writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(),
+ params()->boot_osflags.length()+1);
/**
* find the address of the est_cycle_freq variable and insert it
* so we don't through the lengthly process of trying to
* calculated it by using the PIT, RTC, etc.
*/
- if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
- paddr = vtophys(physmem, addr);
- uint8_t *est_cycle_frequency =
- physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (est_cycle_frequency)
- *(uint64_t *)est_cycle_frequency =
- Clock::Frequency / p->boot_cpu_frequency;
- }
+ if (kernelSymtab->findAddress("est_cycle_freq", addr))
+ virtPort.write(addr, (uint64_t)(Clock::Frequency /
+ p->boot_cpu_frequency));
/**
@@ -100,16 +91,9 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
* @todo At some point we should change ev5.hh and the palcode to support
* 255 ASNs.
*/
- if (kernelSymtab->findAddress("dp264_mv", addr)) {
- paddr = vtophys(physmem, addr);
- char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (dp264_mv) {
- *(uint32_t*)(dp264_mv+0x18) = LittleEndianGuest::htog((uint32_t)127);
- } else
- panic("could not translate dp264_mv addr\n");
-
- } else
+ if (kernelSymtab->findAddress("dp264_mv", addr))
+ virtPort.write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127));
+ else
panic("could not find dp264_mv\n");
#ifndef NDEBUG
@@ -190,15 +174,10 @@ LinuxAlphaSystem::setDelayLoop(ExecContext *xc)
{
Addr addr = 0;
if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
- Addr paddr = vtophys(physmem, addr);
-
- uint8_t *loops_per_jiffy =
- physmem->dma_addr(paddr, sizeof(uint32_t));
-
Tick cpuFreq = xc->getCpuPtr()->frequency();
Tick intrFreq = platform->intrFrequency();
- *(uint32_t *)loops_per_jiffy =
- (uint32_t)((cpuFreq / intrFreq) * 0.9988);
+ xc->getVirtPort(xc)->write(addr,
+ (uint32_t)((cpuFreq / intrFreq) * 0.9988));
}
}
@@ -224,7 +203,6 @@ LinuxAlphaSystem::PrintThreadInfo::process(ExecContext *xc)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
SimObjectParam<PhysicalMemory *> physmem;
Param<string> kernel;
@@ -247,7 +225,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
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"),
@@ -269,7 +246,6 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem)
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;
diff --git a/arch/alpha/linux/system.hh b/arch/alpha/linux/system.hh
index 035e2a427..0c1fb037e 100644
--- a/arch/alpha/linux/system.hh
+++ b/arch/alpha/linux/system.hh
@@ -39,7 +39,6 @@ class IdleStartEvent;
using namespace AlphaISA;
using namespace Linux;
-using namespace std;
/**
* This class contains linux specific system code (Loading, Events, Binning).
diff --git a/arch/alpha/process.cc b/arch/alpha/process.cc
index b2dbe7ad1..25ee79692 100644
--- a/arch/alpha/process.cc
+++ b/arch/alpha/process.cc
@@ -26,28 +26,44 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/constants.hh"
#include "arch/alpha/process.hh"
+#include "arch/alpha/linux/process.hh"
+#include "arch/alpha/tru64/process.hh"
+#include "base/loader/object_file.hh"
+#include "base/misc.hh"
+#include "cpu/exec_context.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
-namespace AlphaISA
-{
-LiveProcess *
-createProcess(const std::string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
+using namespace AlphaISA;
+using namespace std;
+
+AlphaLiveProcess *
+AlphaLiveProcess::create(const std::string &nm, System *system, int stdin_fd,
+ int stdout_fd, int stderr_fd, std::string executable,
std::vector<std::string> &argv, std::vector<std::string> &envp)
{
- LiveProcess * process = NULL;
+ AlphaLiveProcess *process = NULL;
+
+ ObjectFile *objFile = createObjectFile(executable);
+ if (objFile == NULL) {
+ fatal("Can't load object file %s", executable);
+ }
+
+
if (objFile->getArch() != ObjectFile::Alpha)
fatal("Object file does not match architecture.");
switch (objFile->getOpSys()) {
case ObjectFile::Tru64:
- process = new AlphaTru64Process(nm, objFile,
+ process = new AlphaTru64Process(nm, objFile, system,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
break;
case ObjectFile::Linux:
- process = new AlphaLinuxProcess(nm, objFile,
+ process = new AlphaLinuxProcess(nm, objFile, system,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
break;
@@ -55,7 +71,97 @@ createProcess(const std::string &nm, ObjectFile * objFile,
default:
fatal("Unknown/unsupported operating system.");
}
+
+ if (process == NULL)
+ fatal("Unknown error creating process object.");
return process;
}
-} // namespace AlphaISA
+AlphaLiveProcess::AlphaLiveProcess(const std::string &nm, ObjectFile *objFile,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
+ : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
+ argv, envp)
+{
+ brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
+ brk_point = roundUp(brk_point, VMPageSize);
+
+ // Set up stack. On Alpha, stack goes below text section. This
+ // code should get moved to some architecture-specific spot.
+ stack_base = objFile->textBase() - (409600+4096);
+
+ // Set up region for mmaps. Tru64 seems to start just above 0 and
+ // grow up from there.
+ mmap_start = mmap_end = 0x10000;
+
+ // Set pointer for next thread stack. Reserve 8M for main stack.
+ next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+
+}
+
+void
+AlphaLiveProcess::startup()
+{
+ argsInit(MachineBytes, VMPageSize);
+
+ execContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer());
+}
+
+
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaLiveProcess)
+
+ VectorParam<string> cmd;
+ Param<string> executable;
+ Param<string> input;
+ Param<string> output;
+ VectorParam<string> env;
+ SimObjectParam<System *> system;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaLiveProcess)
+
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaLiveProcess)
+
+ INIT_PARAM(cmd, "command line (executable plus arguments)"),
+ INIT_PARAM(executable, "executable (overrides cmd[0] if set)"),
+ INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
+ INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
+ INIT_PARAM(env, "environment settings"),
+ INIT_PARAM(system, "system")
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaLiveProcess)
+
+
+CREATE_SIM_OBJECT(AlphaLiveProcess)
+{
+ string in = input;
+ string out = output;
+
+ // initialize file descriptors to default: same as simulator
+ int stdin_fd, stdout_fd, stderr_fd;
+
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else
+ stdin_fd = Process::openInputFile(input);
+
+ if (out == "stdout" || out == "cout")
+ stdout_fd = STDOUT_FILENO;
+ else if (out == "stderr" || out == "cerr")
+ stdout_fd = STDERR_FILENO;
+ else
+ stdout_fd = Process::openOutputFile(out);
+
+ stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+
+ return AlphaLiveProcess::create(getInstanceName(), system,
+ stdin_fd, stdout_fd, stderr_fd,
+ (string)executable == "" ? cmd[0] : executable,
+ cmd, env);
+}
+
+
+REGISTER_SIM_OBJECT("AlphaLiveProcess", AlphaLiveProcess)
+
diff --git a/arch/alpha/process.hh b/arch/alpha/process.hh
index 4a2a4212e..d97b36e2d 100644
--- a/arch/alpha/process.hh
+++ b/arch/alpha/process.hh
@@ -30,19 +30,35 @@
#define __ALPHA_PROCESS_HH__
#include <string>
+#include <vector>
+#include "sim/process.hh"
-#include "arch/alpha/linux/process.hh"
-#include "arch/alpha/tru64/process.hh"
-#include "base/loader/object_file.hh"
+class ObjectFile;
+class System;
-namespace AlphaISA
+
+class AlphaLiveProcess : public LiveProcess
{
+ protected:
+ AlphaLiveProcess(const std::string &nm, ObjectFile *objFile,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
+
+ void startup();
+
+ public:
+ // this function is used to create the LiveProcess object, since
+ // we can't tell which subclass of LiveProcess to use until we
+ // open and look at the object file.
+ static AlphaLiveProcess *create(const std::string &nm,
+ System *_system,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::string executable,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
-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/regfile.hh b/arch/alpha/regfile.hh
new file mode 100644
index 000000000..af01b7829
--- /dev/null
+++ b/arch/alpha/regfile.hh
@@ -0,0 +1,278 @@
+/*
+ * 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_ALPHA_REGFILE_HH__
+#define __ARCH_ALPHA_REGFILE_HH__
+
+#include "arch/alpha/types.hh"
+#include "arch/alpha/constants.hh"
+#include "sim/faults.hh"
+
+class Checkpoint;
+class ExecContext;
+
+namespace AlphaISA
+{
+ class IntRegFile
+ {
+ protected:
+ IntReg regs[NumIntRegs];
+
+ public:
+
+ IntReg readReg(int intReg)
+ {
+ return regs[intReg];
+ }
+
+ Fault setReg(int intReg, const IntReg &val)
+ {
+ regs[intReg] = val;
+ return NoFault;
+ }
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ };
+
+ class FloatRegFile
+ {
+ public:
+
+ union {
+ uint64_t q[NumFloatRegs]; // integer qword view
+ double d[NumFloatRegs]; // double-precision floating point view
+ };
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ };
+
+ 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
+
+ public:
+ MiscReg readReg(int misc_reg);
+
+ MiscReg readRegWithEffect(int misc_reg, Fault &fault,
+ ExecContext *xc);
+
+ //These functions should be removed once the simplescalar cpu model
+ //has been replaced.
+ int getInstAsid();
+ int getDataAsid();
+
+ Fault setReg(int misc_reg, const MiscReg &val);
+
+ Fault setRegWithEffect(int misc_reg, const MiscReg &val,
+ ExecContext *xc);
+
+#if FULL_SYSTEM
+ protected:
+ typedef uint64_t InternalProcReg;
+
+ InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
+
+ private:
+ InternalProcReg readIpr(int idx, Fault &fault, ExecContext *xc);
+
+ Fault setIpr(int idx, InternalProcReg val, ExecContext *xc);
+#endif
+ friend class RegFile;
+ };
+
+ class RegFile {
+
+ protected:
+ Addr pc; // program counter
+ Addr npc; // next-cycle program counter
+ Addr nnpc;
+
+ public:
+ Addr readPC()
+ {
+ return pc;
+ }
+
+ void setPC(Addr val)
+ {
+ pc = val;
+ }
+
+ Addr readNextPC()
+ {
+ return npc;
+ }
+
+ void setNextPC(Addr val)
+ {
+ npc = val;
+ }
+
+ Addr readNextNPC()
+ {
+ return nnpc;
+ }
+
+ void setNextNPC(Addr val)
+ {
+ nnpc = val;
+ }
+
+ protected:
+ IntRegFile intRegFile; // (signed) integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegFile; // control register file
+
+ public:
+
+#if FULL_SYSTEM
+ int intrflag; // interrupt flag
+ inline int instAsid()
+ { return miscRegFile.getInstAsid(); }
+ inline int dataAsid()
+ { return miscRegFile.getDataAsid(); }
+#endif // FULL_SYSTEM
+
+ void clear()
+ {
+ bzero(&intRegFile, sizeof(intRegFile));
+ bzero(&floatRegFile, sizeof(floatRegFile));
+ bzero(&miscRegFile, sizeof(miscRegFile));
+ }
+
+ MiscReg readMiscReg(int miscReg)
+ {
+ return miscRegFile.readReg(miscReg);
+ }
+
+ MiscReg readMiscRegWithEffect(int miscReg,
+ Fault &fault, ExecContext *xc)
+ {
+ fault = NoFault;
+ return miscRegFile.readRegWithEffect(miscReg, fault, xc);
+ }
+
+ Fault setMiscReg(int miscReg, const MiscReg &val)
+ {
+ return miscRegFile.setReg(miscReg, val);
+ }
+
+ Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
+ ExecContext * xc)
+ {
+ return miscRegFile.setRegWithEffect(miscReg, val, xc);
+ }
+
+ FloatReg readFloatReg(int floatReg)
+ {
+ return floatRegFile.d[floatReg];
+ }
+
+ FloatReg readFloatReg(int floatReg, int width)
+ {
+ return readFloatReg(floatReg);
+ }
+
+ FloatRegBits readFloatRegBits(int floatReg)
+ {
+ return floatRegFile.q[floatReg];
+ }
+
+ FloatRegBits readFloatRegBits(int floatReg, int width)
+ {
+ return readFloatRegBits(floatReg);
+ }
+
+ Fault setFloatReg(int floatReg, const FloatReg &val)
+ {
+ floatRegFile.d[floatReg] = val;
+ return NoFault;
+ }
+
+ Fault setFloatReg(int floatReg, const FloatReg &val, int width)
+ {
+ return setFloatReg(floatReg, val);
+ }
+
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
+ {
+ floatRegFile.q[floatReg] = val;
+ return NoFault;
+ }
+
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
+ {
+ return setFloatRegBits(floatReg, val);
+ }
+
+ IntReg readIntReg(int intReg)
+ {
+ return intRegFile.readReg(intReg);
+ }
+
+ Fault setIntReg(int intReg, const IntReg &val)
+ {
+ return intRegFile.setReg(intReg, val);
+ }
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ enum ContextParam
+ {
+ CONTEXT_PALMODE
+ };
+
+ typedef bool ContextVal;
+
+ void changeContext(ContextParam param, ContextVal val)
+ {
+ //This would be an alternative place to call/implement
+ //the swapPALShadow function
+ }
+ };
+
+ void copyRegs(ExecContext *src, ExecContext *dest);
+
+ void copyMiscRegs(ExecContext *src, ExecContext *dest);
+
+#if FULL_SYSTEM
+ void copyIprs(ExecContext *src, ExecContext *dest);
+#endif
+} // namespace AlphaISA
+
+#endif
diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc
index 26656ab5c..8691e12dc 100644
--- a/arch/alpha/stacktrace.cc
+++ b/arch/alpha/stacktrace.cc
@@ -47,23 +47,23 @@ ProcessInfo::ProcessInfo(ExecContext *_xc)
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));
+ thread_info_size = gtoh(xc->getVirtPort()->read<int32_t>(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));
+ task_struct_size = gtoh(xc->getVirtPort()->read<int32_t>(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));
+ task_off = gtoh(xc->getVirtPort()->read<int32_t>(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));
+ pid_off = gtoh(xc->getVirtPort()->read<int32_t>(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));
+ name_off = gtoh(xc->getVirtPort()->read<int32_t>(addr));
}
Addr
@@ -73,9 +73,7 @@ ProcessInfo::task(Addr ksp) const
if (base == ULL(0xfffffc0000000000))
return 0;
- Addr task;
- CopyOut(xc, &task, base + task_off, sizeof(task));
- return task;
+ return gtoh(xc->getVirtPort()->read<Addr>(base + task_off));
}
int
@@ -85,9 +83,7 @@ ProcessInfo::pid(Addr ksp) const
if (!task)
return -1;
- uint16_t pid;
- CopyOut(xc, &pid, task + pid_off, sizeof(pid));
- return pid;
+ return gtoh(xc->getVirtPort()->read<uint16_t>(task + pid_off));
}
string
@@ -98,7 +94,7 @@ ProcessInfo::name(Addr ksp) const
return "console";
char comm[256];
- CopyString(xc, comm, task + name_off, sizeof(comm));
+ CopyStringOut(xc, comm, task + name_off, sizeof(comm));
if (!comm[0])
return "startup";
diff --git a/arch/alpha/system.cc b/arch/alpha/system.cc
index 25543da57..4234019cd 100644
--- a/arch/alpha/system.cc
+++ b/arch/alpha/system.cc
@@ -26,14 +26,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/ev5.hh"
#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 "mem/physical.hh"
#include "sim/byteswap.hh"
#include "sim/builder.hh"
@@ -62,8 +62,8 @@ AlphaSystem::AlphaSystem(Params *p)
// Load program sections into memory
- pal->loadSections(physmem, true);
- console->loadSections(physmem, true);
+ pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
+ console->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
// load symbols
if (!console->loadGlobalSymbols(consoleSymtab))
@@ -96,11 +96,8 @@ AlphaSystem::AlphaSystem(Params *p)
* 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());
+ virtPort.writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(),
+ strlen(params()->boot_osflags.c_str()));
}
/**
@@ -108,14 +105,11 @@ AlphaSystem::AlphaSystem(Params *p)
* 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);
+ uint64_t data;
+ data = htog(params()->system_type);
+ virtPort.write(addr+0x50, data);
+ data = htog(params()->system_rev);
+ virtPort.write(addr+0x58, data);
} else
panic("could not find hwrpb\n");
@@ -171,16 +165,13 @@ AlphaSystem::fixFuncEventAddr(Addr addr)
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);
+ uint32_t i1 = virtPort.read<uint32_t>(addr);
+ uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(AlphaISA::MachInst));
if ((i1 & inst_mask) == gp_ldah_pattern &&
(i2 & inst_mask) == gp_lda_pattern) {
- Addr new_addr = addr + 2*sz;
+ Addr new_addr = addr + 2* sizeof(AlphaISA::MachInst);
DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
return new_addr;
} else {
@@ -194,14 +185,7 @@ 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));
+ virtPort.write(addr, htog(EV5::Phys2K0Seg(access)));
} else
panic("could not find m5AlphaAccess\n");
}
@@ -233,7 +217,6 @@ AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
SimObjectParam<PhysicalMemory *> physmem;
Param<std::string> kernel;
@@ -256,7 +239,6 @@ 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"),
@@ -278,7 +260,6 @@ 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;
diff --git a/arch/alpha/system.hh b/arch/alpha/system.hh
index fe1307ac3..924e16826 100644
--- a/arch/alpha/system.hh
+++ b/arch/alpha/system.hh
@@ -45,7 +45,6 @@ class AlphaSystem : public System
{
std::string console_path;
std::string palcode;
- std::string boot_osflags;
uint64_t system_type;
uint64_t system_rev;
};
diff --git a/arch/alpha/tlb.cc b/arch/alpha/tlb.cc
index e30a8e595..877822c31 100644
--- a/arch/alpha/tlb.cc
+++ b/arch/alpha/tlb.cc
@@ -93,8 +93,8 @@ AlphaTLB::lookup(Addr vpn, uint8_t asn) const
}
-void
-AlphaTLB::checkCacheability(MemReqPtr &req)
+Fault
+AlphaTLB::checkCacheability(RequestPtr &req)
{
// in Alpha, cacheability is controlled by upper-level bits of the
// physical address
@@ -109,33 +109,24 @@ AlphaTLB::checkCacheability(MemReqPtr &req)
#if ALPHA_TLASER
- if (req->paddr & PAddrUncachedBit39) {
+ if (req->getPaddr() & PAddrUncachedBit39) {
#else
- if (req->paddr & PAddrUncachedBit43) {
+ if (req->getPaddr() & PAddrUncachedBit43) {
#endif
// IPR memory space not implemented
- if (PAddrIprSpace(req->paddr)) {
- if (!req->xc->misspeculating()) {
- switch (req->paddr) {
- case ULL(0xFFFFF00188):
- req->data = 0;
- break;
-
- default:
- panic("IPR memory space not implemented! PA=%x\n",
- req->paddr);
- }
- }
+ if (PAddrIprSpace(req->getPaddr())) {
+ return new UnimpFault("IPR memory space not implemented!");
} else {
// mark request as uncacheable
- req->flags |= UNCACHEABLE;
+ req->setFlags(req->getFlags() | UNCACHEABLE);
#if !ALPHA_TLASER
// Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
- req->paddr &= PAddrUncachedMask;
+ req->setPaddr(req->getPaddr() & PAddrUncachedMask);
#endif
}
}
+ return NoFault;
}
@@ -290,38 +281,24 @@ AlphaITB::regStats()
accesses = hits + misses;
}
-void
-AlphaITB::fault(Addr pc, ExecContext *xc) const
-{
- if (!xc->misspeculating()) {
- xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
- xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
- xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
- (AlphaISA::VAddr(pc).vpn() << 3));
- }
-}
-
Fault
-AlphaITB::translate(MemReqPtr &req) const
+AlphaITB::translate(RequestPtr &req, ExecContext *xc) const
{
- ExecContext *xc = req->xc;
-
- if (AlphaISA::PcPAL(req->vaddr)) {
+ if (AlphaISA::PcPAL(req->getVaddr())) {
// strip off PAL PC marker (lsb is 1)
- req->paddr = (req->vaddr & ~3) & PAddrImplMask;
+ req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
hits++;
return NoFault;
}
- if (req->flags & PHYSICAL) {
- req->paddr = req->vaddr;
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
} else {
// verify that this is a good virtual address
- if (!validVirtualAddress(req->vaddr)) {
- fault(req->vaddr, req->xc);
+ if (!validVirtualAddress(req->getVaddr())) {
acv++;
- return new ItbAcvFault;
+ return new ItbAcvFault(req->getVaddr());
}
@@ -329,50 +306,48 @@ AlphaITB::translate(MemReqPtr &req) const
// VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
#if ALPHA_TLASER
if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->vaddr) == 2) {
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
#else
- if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
#endif
// only valid in kernel mode
if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
AlphaISA::mode_kernel) {
- fault(req->vaddr, req->xc);
acv++;
- return new ItbAcvFault;
+ return new ItbAcvFault(req->getVaddr());
}
- req->paddr = req->vaddr & PAddrImplMask;
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
#if !ALPHA_TLASER
// sign extend the physical address properly
- if (req->paddr & PAddrUncachedBit40)
- req->paddr |= ULL(0xf0000000000);
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
else
- req->paddr &= ULL(0xffffffffff);
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
#endif
} 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(),
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(),
asn);
if (!pte) {
- fault(req->vaddr, req->xc);
misses++;
- return new ItbPageFault;
+ return new ItbPageFault(req->getVaddr());
}
- req->paddr = (pte->ppn << AlphaISA::PageShift) +
- (AlphaISA::VAddr(req->vaddr).offset() & ~3);
+ req->setPaddr((pte->ppn << AlphaISA::PageShift) +
+ (AlphaISA::VAddr(req->getVaddr()).offset()
+ & ~3));
// check permissions for this access
if (!(pte->xre &
(1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
// instruction access fault
- fault(req->vaddr, req->xc);
acv++;
- return new ItbAcvFault;
+ return new ItbAcvFault(req->getVaddr());
}
hits++;
@@ -380,12 +355,11 @@ AlphaITB::translate(MemReqPtr &req) const
}
// check that the physical address is ok (catch bad physical addresses)
- if (req->paddr & ~PAddrImplMask)
+ if (req->getPaddr() & ~PAddrImplMask)
return genMachineCheckFault();
- checkCacheability(req);
+ return checkCacheability(req);
- return NoFault;
}
///////////////////////////////////////////////////////////////////////
@@ -465,38 +439,9 @@ AlphaDTB::regStats()
accesses = read_accesses + write_accesses;
}
-void
-AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
-{
- ExecContext *xc = req->xc;
- AlphaISA::VAddr vaddr = req->vaddr;
-
- // Set fault address and flags. Even though we're modeling an
- // EV5, we use the EV6 technique of not latching fault registers
- // on VPTE loads (instead of locking the registers until IPR_VA is
- // read, like the EV5). The EV6 approach is cleaner and seems to
- // work with EV5 PAL code, but not the other way around.
- if (!xc->misspeculating()
- && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
- // set VA register with faulting address
- xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr);
-
- // set MM_STAT register flags
- xc->setMiscReg(AlphaISA::IPR_MM_STAT,
- (((Opcode(xc->getInst()) & 0x3f) << 11)
- | ((Ra(xc->getInst()) & 0x1f) << 6)
- | (flags & 0x3f)));
-
- // set VA_FORM register with faulting formatted address
- xc->setMiscReg(AlphaISA::IPR_VA_FORM,
- xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
- }
-}
-
Fault
-AlphaDTB::translate(MemReqPtr &req, bool write) const
+AlphaDTB::translate(RequestPtr &req, ExecContext *xc, bool write) const
{
- ExecContext *xc = req->xc;
Addr pc = xc->readPC();
AlphaISA::mode_type mode =
@@ -506,58 +451,57 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
/**
* Check for alignment faults
*/
- if (req->vaddr & (req->size - 1)) {
- fault(req, write ? MM_STAT_WR_MASK : 0);
- DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
- req->size);
- return genAlignmentFault();
+ if (req->getVaddr() & (req->getSize() - 1)) {
+ DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
+ req->getSize());
+ uint64_t flags = write ? MM_STAT_WR_MASK : 0;
+ return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
}
if (pc & 0x1) {
- mode = (req->flags & ALTMODE) ?
+ mode = (req->getFlags() & ALTMODE) ?
(AlphaISA::mode_type)ALT_MODE_AM(
xc->readMiscReg(AlphaISA::IPR_ALT_MODE))
: AlphaISA::mode_kernel;
}
- if (req->flags & PHYSICAL) {
- req->paddr = req->vaddr;
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
} else {
// verify that this is a good virtual address
- if (!validVirtualAddress(req->vaddr)) {
- fault(req, (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_BAD_VA_MASK |
- MM_STAT_ACV_MASK);
-
+ if (!validVirtualAddress(req->getVaddr())) {
if (write) { write_acv++; } else { read_acv++; }
- return new DtbPageFault;
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_BAD_VA_MASK |
+ MM_STAT_ACV_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
}
// Check for "superpage" mapping
#if ALPHA_TLASER
if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->vaddr) == 2) {
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
#else
- if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
#endif
// only valid in kernel mode
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 new DtbAcvFault;
+ uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
}
- req->paddr = req->vaddr & PAddrImplMask;
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
#if !ALPHA_TLASER
// sign extend the physical address properly
- if (req->paddr & PAddrUncachedBit40)
- req->paddr |= ULL(0xf0000000000);
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
else
- req->paddr &= ULL(0xffffffffff);
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
#endif
} else {
@@ -569,48 +513,50 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
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(),
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(),
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) ?
- (Fault)(new PDtbMissFault) :
- (Fault)(new NDtbMissFault);
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_DTB_MISS_MASK;
+ return (req->getFlags() & VPTE) ?
+ (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
+ flags)) :
+ (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
+ flags));
}
- req->paddr = (pte->ppn << AlphaISA::PageShift) +
- AlphaISA::VAddr(req->vaddr).offset();
+ req->setPaddr((pte->ppn << AlphaISA::PageShift) +
+ AlphaISA::VAddr(req->getVaddr()).offset());
if (write) {
if (!(pte->xwe & MODE2MASK(mode))) {
// declare the instruction access fault
- fault(req, MM_STAT_WR_MASK |
- MM_STAT_ACV_MASK |
- (pte->fonw ? MM_STAT_FONW_MASK : 0));
write_acv++;
- return new DtbPageFault;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_ACV_MASK |
+ (pte->fonw ? MM_STAT_FONW_MASK : 0);
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
}
if (pte->fonw) {
- fault(req, MM_STAT_WR_MASK |
- MM_STAT_FONW_MASK);
write_acv++;
- return new DtbPageFault;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_FONW_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
}
} else {
if (!(pte->xre & MODE2MASK(mode))) {
- fault(req, MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0));
read_acv++;
- return new DtbAcvFault;
+ uint64_t flags = MM_STAT_ACV_MASK |
+ (pte->fonr ? MM_STAT_FONR_MASK : 0);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
}
if (pte->fonr) {
- fault(req, MM_STAT_FONR_MASK);
read_acv++;
- return new DtbPageFault;
+ uint64_t flags = MM_STAT_FONR_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
}
}
}
@@ -622,12 +568,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
}
// check that the physical address is ok (catch bad physical addresses)
- if (req->paddr & ~PAddrImplMask)
+ if (req->getPaddr() & ~PAddrImplMask)
return genMachineCheckFault();
- checkCacheability(req);
-
- return NoFault;
+ return checkCacheability(req);
}
AlphaISA::PTE &
diff --git a/arch/alpha/tlb.hh b/arch/alpha/tlb.hh
index de955fa46..f6256020e 100644
--- a/arch/alpha/tlb.hh
+++ b/arch/alpha/tlb.hh
@@ -31,10 +31,11 @@
#include <map>
+#include "arch/alpha/ev5.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/faults.hh"
#include "base/statistics.hh"
-#include "mem/mem_req.hh"
+#include "mem/request.hh"
#include "sim/sim_object.hh"
class ExecContext;
@@ -72,7 +73,7 @@ class AlphaTLB : public SimObject
return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
}
- static void checkCacheability(MemReqPtr &req);
+ static Fault checkCacheability(RequestPtr &req);
// Checkpointing
virtual void serialize(std::ostream &os);
@@ -87,14 +88,11 @@ class AlphaITB : public AlphaTLB
mutable Stats::Scalar<> acv;
mutable Stats::Formula accesses;
- protected:
- void fault(Addr pc, ExecContext *xc) const;
-
public:
AlphaITB(const std::string &name, int size);
virtual void regStats();
- Fault translate(MemReqPtr &req) const;
+ Fault translate(RequestPtr &req, ExecContext *xc) const;
};
class AlphaDTB : public AlphaTLB
@@ -113,14 +111,11 @@ class AlphaDTB : public AlphaTLB
Stats::Formula acv;
Stats::Formula accesses;
- protected:
- void fault(MemReqPtr &req, uint64_t flags) const;
-
public:
AlphaDTB(const std::string &name, int size);
virtual void regStats();
- Fault translate(MemReqPtr &req, bool write) const;
+ Fault translate(RequestPtr &req, ExecContext *xc, bool write) const;
};
#endif // __ALPHA_MEMORY_HH__
diff --git a/arch/alpha/tru64/process.cc b/arch/alpha/tru64/process.cc
index ae83bb649..55f75f7d0 100644
--- a/arch/alpha/tru64/process.cc
+++ b/arch/alpha/tru64/process.cc
@@ -26,11 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/tru64/tru64.hh"
#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/process.hh"
#include "sim/syscall_emul.hh"
@@ -42,7 +44,7 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
- TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
+ TypedBufferArg<AlphaTru64::utsname> name(xc->getSyscallArg(0));
strcpy(name->sysname, "OSF1");
strcpy(name->nodename, "m5.eecs.umich.edu");
@@ -50,7 +52,7 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process,
strcpy(name->version, "732");
strcpy(name->machine, "alpha");
- name.copyOut(xc->getMemPtr());
+ name.copyOut(xc->getMemPort());
return 0;
}
@@ -64,29 +66,29 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
switch (op) {
- case Tru64::GSI_MAX_CPU: {
+ case AlphaTru64::GSI_MAX_CPU: {
TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
*max_cpu = htog((uint32_t)process->numCpus());
- max_cpu.copyOut(xc->getMemPtr());
+ max_cpu.copyOut(xc->getMemPort());
return 1;
}
- case Tru64::GSI_CPUS_IN_BOX: {
+ case AlphaTru64::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());
+ cpus_in_box.copyOut(xc->getMemPort());
return 1;
}
- case Tru64::GSI_PHYSMEM: {
+ case AlphaTru64::GSI_PHYSMEM: {
TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
*physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
- physmem.copyOut(xc->getMemPtr());
+ physmem.copyOut(xc->getMemPort());
return 1;
}
- case Tru64::GSI_CPU_INFO: {
- TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
+ case AlphaTru64::GSI_CPU_INFO: {
+ TypedBufferArg<AlphaTru64::cpu_info> infop(xc->getSyscallArg(1));
infop->current_cpu = htog(0);
infop->cpus_in_box = htog(process->numCpus());
@@ -98,30 +100,30 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
infop->cpu_ex_binding = htog(0);
infop->mhz = htog(667);
- infop.copyOut(xc->getMemPtr());
+ infop.copyOut(xc->getMemPort());
return 1;
}
- case Tru64::GSI_PROC_TYPE: {
+ case AlphaTru64::GSI_PROC_TYPE: {
TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
*proc_type = htog((uint64_t)11);
- proc_type.copyOut(xc->getMemPtr());
+ proc_type.copyOut(xc->getMemPort());
return 1;
}
- case Tru64::GSI_PLATFORM_NAME: {
+ case AlphaTru64::GSI_PLATFORM_NAME: {
BufferArg bufArg(xc->getSyscallArg(1), nbytes);
strncpy((char *)bufArg.bufferPtr(),
"COMPAQ Professional Workstation XP1000",
nbytes);
- bufArg.copyOut(xc->getMemPtr());
+ bufArg.copyOut(xc->getMemPort());
return 1;
}
- case Tru64::GSI_CLK_TCK: {
+ case AlphaTru64::GSI_CLK_TCK: {
TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
*clk_hz = htog((uint64_t)1024);
- clk_hz.copyOut(xc->getMemPtr());
+ clk_hz.copyOut(xc->getMemPort());
return 1;
}
@@ -141,7 +143,7 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
unsigned op = xc->getSyscallArg(0);
switch (op) {
- case Tru64::SSI_IEEE_FP_CONTROL:
+ case AlphaTru64::SSI_IEEE_FP_CONTROL:
warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
xc->getSyscallArg(1));
break;
@@ -155,8 +157,48 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
}
+/// Target table() handler.
+static
+SyscallReturn tableFunc(SyscallDesc *desc, int callnum,Process *process,
+ ExecContext *xc)
+{
+ using namespace std;
+ using namespace TheISA;
+
+ 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 AlphaTru64::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->getMemPort());
+ return 0;
+ }
+
+ default:
+ cerr << "table(): id " << id << " unknown." << endl;
+ return -EINVAL;
+ }
+}
+
SyscallDesc AlphaTru64Process::syscallDescs[] = {
- /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc,
+ /* 0 */ SyscallDesc("syscall (#0)", AlphaTru64::indirectSyscallFunc,
SyscallDesc::SuppressReturnValue),
/* 1 */ SyscallDesc("exit", exitFunc),
/* 2 */ SyscallDesc("fork", unimplementedFunc),
@@ -202,7 +244,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 42 */ SyscallDesc("pipe", unimplementedFunc),
/* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
/* 44 */ SyscallDesc("profil", unimplementedFunc),
- /* 45 */ SyscallDesc("open", openFunc<Tru64>),
+ /* 45 */ SyscallDesc("open", openFunc<AlphaTru64>),
/* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
/* 47 */ SyscallDesc("getgid", getgidPseudoFunc),
/* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
@@ -211,7 +253,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 51 */ SyscallDesc("acct", unimplementedFunc),
/* 52 */ SyscallDesc("sigpending", unimplementedFunc),
/* 53 */ SyscallDesc("classcntl", unimplementedFunc),
- /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<AlphaTru64>),
/* 55 */ SyscallDesc("reboot", unimplementedFunc),
/* 56 */ SyscallDesc("revoke", unimplementedFunc),
/* 57 */ SyscallDesc("symlink", unimplementedFunc),
@@ -224,11 +266,11 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 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>),
+ /* 67 */ SyscallDesc("pre_F64_stat", statFunc<AlphaTru64::PreF64>),
+ /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<AlphaTru64::PreF64>),
/* 69 */ SyscallDesc("sbrk", unimplementedFunc),
/* 70 */ SyscallDesc("sstk", unimplementedFunc),
- /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<AlphaTru64>),
/* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
/* 73 */ SyscallDesc("munmap", munmapFunc),
/* 74 */ SyscallDesc("mprotect", ignoreFunc),
@@ -242,13 +284,13 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
/* 83 */ SyscallDesc("setitimer", unimplementedFunc),
/* 84 */ SyscallDesc("old_wait", unimplementedFunc),
- /* 85 */ SyscallDesc("table", Tru64::tableFunc),
+ /* 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>),
+ /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<AlphaTru64::PreF64>),
/* 92 */ SyscallDesc("fcntl", fcntlFunc),
/* 93 */ SyscallDesc("select", unimplementedFunc),
/* 94 */ SyscallDesc("poll", unimplementedFunc),
@@ -260,7 +302,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 100 */ SyscallDesc("getpriority", unimplementedFunc),
/* 101 */ SyscallDesc("old_send", unimplementedFunc),
/* 102 */ SyscallDesc("old_recv", unimplementedFunc),
- /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc,
+ /* 103 */ SyscallDesc("sigreturn", AlphaTru64::sigreturnFunc,
SyscallDesc::SuppressReturnValue),
/* 104 */ SyscallDesc("bind", unimplementedFunc),
/* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
@@ -274,8 +316,8 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 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>),
+ /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<AlphaTru64>),
+ /* 117 */ SyscallDesc("getrusage", getrusageFunc<AlphaTru64>),
/* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
/* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
/* 120 */ SyscallDesc("readv", unimplementedFunc),
@@ -302,7 +344,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
/* 142 */ SyscallDesc("gethostid", unimplementedFunc),
/* 143 */ SyscallDesc("sethostid", unimplementedFunc),
- /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
+ /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<AlphaTru64>),
/* 145 */ SyscallDesc("setrlimit", ignoreFunc),
/* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
/* 147 */ SyscallDesc("setsid", unimplementedFunc),
@@ -317,9 +359,9 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 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>),
+ /* 159 */ SyscallDesc("getdirentries", AlphaTru64::getdirentriesFunc),
+ /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<AlphaTru64::PreF64>),
+ /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<AlphaTru64::PreF64>),
/* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
/* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
/* 164 */ SyscallDesc("getfh", unimplementedFunc),
@@ -382,11 +424,11 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 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>),
+ /* 224 */ SyscallDesc("stat", statFunc<AlphaTru64::F64>),
+ /* 225 */ SyscallDesc("lstat", lstatFunc<AlphaTru64::F64>),
+ /* 226 */ SyscallDesc("fstat", fstatFunc<AlphaTru64::F64>),
+ /* 227 */ SyscallDesc("statfs", statfsFunc<AlphaTru64::F64>),
+ /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<AlphaTru64::F64>),
/* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
/* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
/* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
@@ -431,13 +473,13 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
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),
+ /* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc),
+ /* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc),
+ /* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc),
+ /* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc),
+ /* 5 */ SyscallDesc("m5_cond_broadcast", AlphaTru64::m5_cond_broadcastFunc),
+ /* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc),
+ /* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc),
/* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 9 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 10 */ SyscallDesc("task_self", unimplementedFunc),
@@ -454,22 +496,22 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 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),
+ /* 24 */ SyscallDesc("nxm_block", AlphaTru64::nxm_blockFunc),
+ /* 25 */ SyscallDesc("nxm_unblock", AlphaTru64::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),
+ /* 32 */ SyscallDesc("nxm_thread_create", AlphaTru64::nxm_thread_createFunc),
+ /* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc),
/* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc),
+ /* 35 */ SyscallDesc("nxm_idle", AlphaTru64::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),
+ /* 39 */ SyscallDesc("nxm_thread_block", AlphaTru64::nxm_thread_blockFunc),
/* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
/* 41 */ SyscallDesc("init_process", unimplementedFunc),
/* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
@@ -477,7 +519,7 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
/* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
/* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
- /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc),
+ /* 47 */ SyscallDesc("stack_create", AlphaTru64::stack_createFunc),
/* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
/* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
/* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
@@ -489,7 +531,7 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
/* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc),
+ /* 59 */ SyscallDesc("swtch_pri", AlphaTru64::swtch_priFunc),
/* 60 */ SyscallDesc("swtch", unimplementedFunc),
/* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
/* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
@@ -497,7 +539,7 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 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),
+ /* 67 */ SyscallDesc("nxm_swtch_pri", AlphaTru64::swtch_priFunc),
/* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
/* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
@@ -530,12 +572,14 @@ AlphaTru64Process::getDesc(int callnum)
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, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ : AlphaLiveProcess(name, objFile, system, 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/tru64/process.hh b/arch/alpha/tru64/process.hh
index 051760702..1cde4cac0 100644
--- a/arch/alpha/tru64/process.hh
+++ b/arch/alpha/tru64/process.hh
@@ -29,15 +29,17 @@
#ifndef __ALPHA_TRU64_PROCESS_HH__
#define __ALPHA_TRU64_PROCESS_HH__
-#include "sim/process.hh"
+#include "arch/alpha/process.hh"
+namespace AlphaISA {
/// A process with emulated Alpha Tru64 syscalls.
-class AlphaTru64Process : public LiveProcess
+class AlphaTru64Process : public AlphaLiveProcess
{
public:
/// Constructor.
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);
@@ -54,5 +56,6 @@ class AlphaTru64Process : public LiveProcess
virtual SyscallDesc* getDesc(int callnum);
};
+} // namespace AlphaISA
#endif // __ALPHA_TRU64_PROCESS_HH__
diff --git a/arch/alpha/tru64/system.cc b/arch/alpha/tru64/system.cc
index d09a0c85d..2ad06d679 100644
--- a/arch/alpha/tru64/system.cc
+++ b/arch/alpha/tru64/system.cc
@@ -35,8 +35,8 @@
#include "cpu/exec_context.hh"
#include "kern/tru64/tru64_events.hh"
#include "kern/system_events.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
#include "sim/builder.hh"
using namespace std;
@@ -46,12 +46,7 @@ Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
{
Addr addr = 0;
if (kernelSymtab->findAddress("enable_async_printf", addr)) {
- Addr paddr = vtophys(physmem, addr);
- uint8_t *enable_async_printf =
- physmem->dma_addr(paddr, sizeof(uint32_t));
-
- if (enable_async_printf)
- *(uint32_t *)enable_async_printf = 0;
+ virtPort.write(addr, (uint32_t)0);
}
#ifdef DEBUG
@@ -96,7 +91,6 @@ Tru64AlphaSystem::~Tru64AlphaSystem()
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
SimObjectParam<PhysicalMemory *> physmem;
Param<string> kernel;
@@ -118,7 +112,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
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"),
@@ -139,7 +132,6 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem)
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;
diff --git a/arch/alpha/tru64/tru64.cc b/arch/alpha/tru64/tru64.cc
new file mode 100644
index 000000000..4a3e653c1
--- /dev/null
+++ b/arch/alpha/tru64/tru64.cc
@@ -0,0 +1,70 @@
+/*
+ * 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/tru64/tru64.hh"
+
+// open(2) flags translation table
+OpenFlagTransTable AlphaTru64::openFlagTable[] = {
+#ifdef _MSC_VER
+ { AlphaTru64::TGT_O_RDONLY, _O_RDONLY },
+ { AlphaTru64::TGT_O_WRONLY, _O_WRONLY },
+ { AlphaTru64::TGT_O_RDWR, _O_RDWR },
+ { AlphaTru64::TGT_O_APPEND, _O_APPEND },
+ { AlphaTru64::TGT_O_CREAT, _O_CREAT },
+ { AlphaTru64::TGT_O_TRUNC, _O_TRUNC },
+ { AlphaTru64::TGT_O_EXCL, _O_EXCL },
+#ifdef _O_NONBLOCK
+ { AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+ { AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+ { AlphaTru64::TGT_O_SYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+ { AlphaTru64::TGT_O_RDONLY, O_RDONLY },
+ { AlphaTru64::TGT_O_WRONLY, O_WRONLY },
+ { AlphaTru64::TGT_O_RDWR, O_RDWR },
+ { AlphaTru64::TGT_O_APPEND, O_APPEND },
+ { AlphaTru64::TGT_O_CREAT, O_CREAT },
+ { AlphaTru64::TGT_O_TRUNC, O_TRUNC },
+ { AlphaTru64::TGT_O_EXCL, O_EXCL },
+ { AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK },
+ { AlphaTru64::TGT_O_NOCTTY, O_NOCTTY },
+#ifdef O_SYNC
+ { AlphaTru64::TGT_O_SYNC, O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int AlphaTru64::NUM_OPEN_FLAGS =
+ (sizeof(AlphaTru64::openFlagTable)/sizeof(AlphaTru64::openFlagTable[0]));
+
+
+
diff --git a/arch/alpha/tru64/tru64.hh b/arch/alpha/tru64/tru64.hh
new file mode 100644
index 000000000..19343ba23
--- /dev/null
+++ b/arch/alpha/tru64/tru64.hh
@@ -0,0 +1,127 @@
+/*
+ * 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_ALPHA_TRU64_HH
+#define __ALPHA_ALPHA_TRU64_HH
+
+#include "kern/tru64/tru64.hh"
+
+class AlphaTru64 : public Tru64
+{
+
+ public:
+ /// 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;
+
+ //@{
+ /// 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
+ //@}
+
+ /// 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 getrusage().
+ static const int TGT_RUSAGE_THREAD = 1;
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
+ //@}
+
+ //@{
+ /// For setsysinfo().
+ static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
+ //@}
+
+ //@{
+ /// 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;
+ //@}
+
+ //@{
+ /// For table().
+ static const int TBL_SYSINFO = 12;
+ //@}
+
+ /// 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
+ };
+};
+
+
+
+#endif
diff --git a/arch/alpha/types.hh b/arch/alpha/types.hh
new file mode 100644
index 000000000..d4cb482d8
--- /dev/null
+++ b/arch/alpha/types.hh
@@ -0,0 +1,64 @@
+/*
+ * 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_ALPHA_TYPES_HH__
+#define __ARCH_ALPHA_TYPES_HH__
+
+#include "sim/host.hh"
+
+namespace AlphaISA
+{
+
+ typedef uint32_t MachInst;
+ typedef uint64_t ExtMachInst;
+ typedef uint8_t RegIndex;
+
+ typedef uint64_t IntReg;
+
+ // floating point register file entry type
+ typedef double FloatReg;
+ typedef uint64_t FloatRegBits;
+
+ // control register file contents
+ typedef uint64_t MiscReg;
+
+ typedef union {
+ IntReg intreg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ enum annotes {
+ ANNOTE_NONE = 0,
+ // An impossible number for instruction annotations
+ ITOUCH_ANNOTE = 0xffffffff,
+ };
+
+} // namespace AlphaISA
+
+#endif
diff --git a/arch/alpha/utility.hh b/arch/alpha/utility.hh
new file mode 100644
index 000000000..6cc916307
--- /dev/null
+++ b/arch/alpha/utility.hh
@@ -0,0 +1,156 @@
+/*
+ * 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_ALPHA_UTILITY_HH__
+#define __ARCH_ALPHA_UTILITY_HH__
+
+#include "config/full_system.hh"
+#include "arch/alpha/types.hh"
+#include "arch/alpha/constants.hh"
+#include "arch/alpha/regfile.hh"
+#include "base/misc.hh"
+
+namespace AlphaISA
+{
+
+ static inline ExtMachInst
+ makeExtMI(MachInst inst, const uint64_t &pc) {
+#if FULL_SYSTEM
+ ExtMachInst ext_inst = inst;
+ if (pc && 0x1)
+ return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
+ else
+ return ext_inst;
+#else
+ return ExtMachInst(inst);
+#endif
+ }
+
+ inline bool isCallerSaveIntegerRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
+ }
+
+ inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return (reg >= 9 && reg <= 15);
+ }
+
+ inline bool isCallerSaveFloatRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ inline bool isCalleeSaveFloatRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ inline Addr alignAddress(const Addr &addr,
+ unsigned int nbytes) {
+ return (addr & ~(nbytes - 1));
+ }
+
+ // 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);
+ }
+
+ 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);
+
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param xc The execution context.
+ */
+ template <class XC>
+ void zeroRegisters(XC *xc);
+
+#if FULL_SYSTEM
+ // Alpha IPR register accessors
+ inline bool PcPAL(Addr addr) { return addr & 0x1; }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Translation stuff
+ //
+
+ inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; }
+
+ // User Virtual
+ inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; }
+
+ // Kernel Direct Mapped
+ inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; }
+ inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; }
+
+ // Kernel Virtual
+ inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; }
+
+ inline Addr
+ TruncPage(Addr addr)
+ { return addr & ~(PageBytes - 1); }
+
+ inline Addr
+ RoundPage(Addr addr)
+ { return (addr + PageBytes - 1) & ~(PageBytes - 1); }
+
+ void initCPU(ExecContext *xc, int cpuId);
+ void initIPRs(ExecContext *xc, int cpuId);
+
+ /**
+ * Function to check for and process any interrupts.
+ * @param xc The execution context.
+ */
+ template <class XC>
+ void processInterrupts(XC *xc);
+#endif
+
+} // namespace AlphaISA
+
+#endif
diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc
index 40261426d..41e9b80a3 100644
--- a/arch/alpha/vtophys.cc
+++ b/arch/alpha/vtophys.cc
@@ -28,33 +28,35 @@
#include <string>
+#include "arch/alpha/ev5.hh"
#include "arch/alpha/vtophys.hh"
+#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "cpu/exec_context.hh"
-#include "mem/functional/physical.hh"
+#include "mem/vport.hh"
using namespace std;
using namespace AlphaISA;
AlphaISA::PageTableEntry
-kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
+AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
{
Addr level1_pte = ptbr + vaddr.level1();
- AlphaISA::PageTableEntry level1 = pmem->phys_read_qword(level1_pte);
+ AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte);
if (!level1.valid()) {
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
return 0;
}
Addr level2_pte = level1.paddr() + vaddr.level2();
- AlphaISA::PageTableEntry level2 = pmem->phys_read_qword(level2_pte);
+ AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte);
if (!level2.valid()) {
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
return 0;
}
Addr level3_pte = level2.paddr() + vaddr.level3();
- AlphaISA::PageTableEntry level3 = pmem->phys_read_qword(level3_pte);
+ AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte);
if (!level3.valid()) {
DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
return 0;
@@ -63,7 +65,7 @@ kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
}
Addr
-vtophys(PhysicalMemory *xc, Addr vaddr)
+AlphaISA::vtophys(Addr vaddr)
{
Addr paddr = 0;
if (AlphaISA::IsUSeg(vaddr))
@@ -79,7 +81,7 @@ vtophys(PhysicalMemory *xc, Addr vaddr)
}
Addr
-vtophys(ExecContext *xc, Addr addr)
+AlphaISA::vtophys(ExecContext *xc, Addr addr)
{
AlphaISA::VAddr vaddr = addr;
Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20);
@@ -95,7 +97,7 @@ vtophys(ExecContext *xc, Addr addr)
paddr = vaddr;
} else {
AlphaISA::PageTableEntry pte =
- kernel_pte_lookup(xc->getPhysMemPtr(), ptbr, vaddr);
+ kernel_pte_lookup(xc->getPhysPort(), ptbr, vaddr);
if (pte.valid())
paddr = pte.paddr() | vaddr.offset();
}
@@ -107,162 +109,54 @@ vtophys(ExecContext *xc, Addr addr)
return paddr;
}
-uint8_t *
-ptomem(ExecContext *xc, Addr paddr, size_t 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->getPhysMemPtr()->dma_addr(paddr, len);
-}
void
-CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
+AlphaISA::CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
{
- Addr paddr;
- char *dmaaddr;
- char *dst = (char *)dest;
- int len;
+ uint8_t *dst = (uint8_t *)dest;
+ VirtualPort *vp = xc->getVirtPort(xc);
- paddr = vtophys(xc, src);
- len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
- (int)cplen);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
- assert(dmaaddr);
+ vp->readBlob(src, dst, cplen);
- memcpy(dst, dmaaddr, len);
- if (len == cplen)
- return;
-
- cplen -= len;
- dst += len;
- src += len;
-
- while (cplen > AlphaISA::PageBytes) {
- paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
- AlphaISA::PageBytes);
- assert(dmaaddr);
-
- memcpy(dst, dmaaddr, AlphaISA::PageBytes);
- cplen -= AlphaISA::PageBytes;
- dst += AlphaISA::PageBytes;
- src += AlphaISA::PageBytes;
- }
+ xc->delVirtPort(vp);
- if (cplen > 0) {
- paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
- assert(dmaaddr);
-
- memcpy(dst, dmaaddr, cplen);
- }
}
void
-CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
+AlphaISA::CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
{
- Addr paddr;
- char *dmaaddr;
- char *src = (char *)source;
- int len;
-
- paddr = vtophys(xc, dest);
- len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
- (int)cplen);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
- assert(dmaaddr);
-
- memcpy(dmaaddr, src, len);
- if (len == cplen)
- return;
-
- cplen -= len;
- src += len;
- dest += len;
-
- while (cplen > AlphaISA::PageBytes) {
- paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
- AlphaISA::PageBytes);
- assert(dmaaddr);
-
- memcpy(dmaaddr, src, AlphaISA::PageBytes);
- cplen -= AlphaISA::PageBytes;
- src += AlphaISA::PageBytes;
- dest += AlphaISA::PageBytes;
- }
+ uint8_t *src = (uint8_t *)source;
+ VirtualPort *vp = xc->getVirtPort(xc);
- if (cplen > 0) {
- paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
- assert(dmaaddr);
+ vp->writeBlob(dest, src, cplen);
- memcpy(dmaaddr, src, cplen);
- }
+ xc->delVirtPort(vp);
}
void
-CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
+AlphaISA::CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
{
- Addr paddr;
- char *dmaaddr;
- int len;
-
- paddr = vtophys(xc, vaddr);
- len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
- (int)maxlen);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
- assert(dmaaddr);
-
- char *term = (char *)memchr(dmaaddr, 0, len);
- if (term)
- len = term - dmaaddr + 1;
-
- memcpy(dst, dmaaddr, len);
-
- if (term || len == maxlen)
- return;
-
- maxlen -= len;
- dst += len;
- vaddr += len;
-
- while (maxlen > AlphaISA::PageBytes) {
- paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
- AlphaISA::PageBytes);
- assert(dmaaddr);
-
- char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
- len = term ? (term - dmaaddr + 1) : AlphaISA::PageBytes;
+ int len = 0;
+ VirtualPort *vp = xc->getVirtPort(xc);
- memcpy(dst, dmaaddr, len);
- if (term)
- return;
+ do {
+ vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
+ len++;
+ } while (len < maxlen && dst[len] != 0 );
- maxlen -= AlphaISA::PageBytes;
- dst += AlphaISA::PageBytes;
- vaddr += AlphaISA::PageBytes;
- }
-
- if (maxlen > 0) {
- paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, maxlen);
- assert(dmaaddr);
-
- char *term = (char *)memchr(dmaaddr, 0, maxlen);
- len = term ? (term - dmaaddr + 1) : maxlen;
-
- memcpy(dst, dmaaddr, len);
+ xc->delVirtPort(vp);
+ dst[len] = 0;
+}
- maxlen -= len;
+void
+AlphaISA::CopyStringIn(ExecContext *xc, char *src, Addr vaddr)
+{
+ VirtualPort *vp = xc->getVirtPort(xc);
+ for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done();
+ gen.next())
+ {
+ vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
+ src += gen.size();
}
-
- if (maxlen == 0)
- dst[maxlen] = '\0';
+ xc->delVirtPort(vp);
}
diff --git a/arch/alpha/vtophys.hh b/arch/alpha/vtophys.hh
index 95430ce77..7ab14bc5b 100644
--- a/arch/alpha/vtophys.hh
+++ b/arch/alpha/vtophys.hh
@@ -32,19 +32,21 @@
#include "arch/alpha/isa_traits.hh"
class ExecContext;
-class PhysicalMemory;
+class FunctionalPort;
-AlphaISA::PageTableEntry
-kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr);
+namespace AlphaISA {
-Addr vtophys(PhysicalMemory *xc, Addr vaddr);
+PageTableEntry
+kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr);
+
+Addr vtophys(Addr vaddr);
Addr vtophys(ExecContext *xc, Addr vaddr);
-uint8_t *vtomem(ExecContext *xc, Addr vaddr, size_t len);
-uint8_t *ptomem(ExecContext *xc, Addr paddr, size_t len);
void CopyOut(ExecContext *xc, void *dst, Addr src, size_t len);
void CopyIn(ExecContext *xc, Addr dst, void *src, size_t len);
-void CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen);
+void CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen);
+void CopyStringIn(ExecContext *xc, char *src, Addr vaddr);
+};
#endif // __ARCH_ALPHA_VTOPHYS_H__
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index 570110d84..a92c85c3f 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -1,5 +1,3 @@
-#! /usr/bin/env python
-
# Copyright (c) 2003-2005 The Regents of The University of Michigan
# All rights reserved.
#
@@ -162,13 +160,12 @@ def t_CPPDIRECTIVE(t):
def t_NEWFILE(t):
r'^\#\#newfile\s+"[\w/.-]*"'
- global fileNameStack
- fileNameStack.append((t.value[11:-1], t.lineno))
+ fileNameStack.push((t.value[11:-1], t.lineno))
t.lineno = 0
def t_ENDFILE(t):
r'^\#\#endfile'
- (filename, t.lineno) = fileNameStack.pop()
+ (old_filename, t.lineno) = fileNameStack.pop()
#
# The functions t_NEWLINE, t_ignore, and t_error are
@@ -698,7 +695,7 @@ def p_error(t):
if t:
error(t.lineno, "syntax error at '%s'" % t.value)
else:
- error_bt(0, "unknown syntax error")
+ error(0, "unknown syntax error", True)
# END OF GRAMMAR RULES
#
@@ -896,6 +893,12 @@ formatStack = Stack(NoFormat())
# The global default case stack.
defaultStack = Stack( None )
+# Global stack that tracks current file and line number.
+# Each element is a tuple (filename, lineno) that records the
+# *current* filename and the line number in the *previous* file where
+# it was included.
+fileNameStack = Stack()
+
###################
# Utility functions
@@ -932,25 +935,22 @@ def fixPythonIndentation(s):
return s
# Error handler. Just call exit. Output formatted to work under
-# 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):
+# Emacs compile-mode. Optional 'print_traceback' arg, if set to True,
+# prints a Python stack backtrace too (can be handy when trying to
+# debug the parser itself).
+def error(lineno, string, print_traceback = False):
spaces = ""
for (filename, line) in fileNameStack[0:-1]:
- print spaces + "In file included from " + filename
+ 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). 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)
- sys.exit(1)
+ # Print a Python stack backtrace if requested.
+ if (print_traceback):
+ traceback.print_exc()
+ if lineno != 0:
+ line_str = "%d:" % lineno
+ else:
+ line_str = ""
+ sys.exit(spaces + "%s:%s %s" % (fileNameStack[-1][0], line_str, string))
#####################################################################
@@ -1070,7 +1070,7 @@ def buildOperandTypeMap(userDict, lineno):
elif size == 64:
ctype = 'double'
if ctype == '':
- error(0, 'Unrecognized type description "%s" in userDict')
+ error(lineno, 'Unrecognized type description "%s" in userDict')
operandTypeMap[ext] = (size, ctype, is_signed)
#
@@ -1217,16 +1217,27 @@ class FloatRegOperand(Operand):
def makeRead(self):
bit_select = 0
+ width = 0;
if (self.ctype == 'float'):
- func = 'readFloatRegSingle'
+ func = 'readFloatReg'
+ width = 32;
elif (self.ctype == 'double'):
- func = 'readFloatRegDouble'
+ func = 'readFloatReg'
+ width = 64;
else:
- func = 'readFloatRegInt'
+ func = 'readFloatRegBits'
+ if (self.ctype == 'uint32_t'):
+ width = 32;
+ elif (self.ctype == 'uint64_t'):
+ width = 64;
if (self.size != self.dflt_size):
bit_select = 1
- base = 'xc->%s(this, %d)' % \
- (func, self.src_reg_idx)
+ if width:
+ base = 'xc->%s(this, %d, %d)' % \
+ (func, self.src_reg_idx, width)
+ else:
+ base = 'xc->%s(this, %d)' % \
+ (func, self.src_reg_idx)
if bit_select:
return '%s = bits(%s, %d, 0);\n' % \
(self.base_name, base, self.size-1)
@@ -1236,21 +1247,34 @@ class FloatRegOperand(Operand):
def makeWrite(self):
final_val = self.base_name
final_ctype = self.ctype
+ widthSpecifier = ''
+ width = 0
if (self.ctype == 'float'):
- func = 'setFloatRegSingle'
+ width = 32
+ func = 'setFloatReg'
elif (self.ctype == 'double'):
- func = 'setFloatRegDouble'
+ width = 64
+ func = 'setFloatReg'
+ elif (self.ctype == 'uint32_t'):
+ func = 'setFloatRegBits'
+ width = 32
+ elif (self.ctype == 'uint64_t'):
+ func = 'setFloatRegBits'
+ width = 64
else:
- func = 'setFloatRegInt'
+ func = 'setFloatRegBits'
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)
+ if width:
+ widthSpecifier = ', %d' % width
wb = '''
{
%s final_val = %s;
- xc->%s(this, %d, final_val);\n
+ xc->%s(this, %d, final_val%s);\n
if (traceData) { traceData->setData(final_val); }
- }''' % (final_ctype, final_val, func, self.dest_reg_idx)
+ }''' % (final_ctype, final_val, func, self.dest_reg_idx,
+ widthSpecifier)
return wb
class ControlRegOperand(Operand):
@@ -1320,7 +1344,7 @@ class NPCOperand(Operand):
return ''
def makeRead(self):
- return '%s = xc->readPC() + 4;\n' % self.base_name
+ return '%s = xc->readNextPC();\n' % self.base_name
def makeWrite(self):
return 'xc->setNextPC(%s);\n' % self.base_name
@@ -1330,7 +1354,7 @@ class NNPCOperand(Operand):
return ''
def makeRead(self):
- return '%s = xc->readPC() + 8;\n' % self.base_name
+ return '%s = xc->readNextNPC();\n' % self.base_name
def makeWrite(self):
return 'xc->setNextNPC(%s);\n' % self.base_name
@@ -1604,13 +1628,27 @@ opClassRE = re.compile(r'.*Op|No_OpClass')
class InstObjParams:
def __init__(self, mnem, class_name, base_class = '',
- code_block = None, opt_args = []):
+ code = None, opt_args = [], *extras):
self.mnemonic = mnem
self.class_name = class_name
self.base_class = base_class
- if code_block:
- for code_attr in code_block.__dict__.keys():
- setattr(self, code_attr, getattr(code_block, code_attr))
+ if code:
+ #If the user already made a CodeBlock, pick the parts from it
+ if isinstance(code, CodeBlock):
+ origCode = code.orig_code
+ codeBlock = code
+ else:
+ origCode = code
+ codeBlock = CodeBlock(code)
+ compositeCode = '\n'.join([origCode] +
+ [pair[1] for pair in extras])
+ compositeBlock = CodeBlock(compositeCode)
+ for code_attr in compositeBlock.__dict__.keys():
+ setattr(self, code_attr, getattr(compositeBlock, code_attr))
+ for (key, snippet) in extras:
+ setattr(self, key, CodeBlock(snippet).code)
+ self.code = codeBlock.code
+ self.orig_code = origCode
else:
self.constructor = ''
self.flags = []
@@ -1687,47 +1725,47 @@ def update_if_needed(file, contents):
f.write(contents)
f.close()
-# This regular expression matches include directives
+# This regular expression matches '##include' directives
includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
re.MULTILINE)
-def preprocess_isa_desc(isa_desc):
+# Function to replace a matched '##include' directive with the
+# contents of the specified file (with nested ##includes replaced
+# recursively). 'matchobj' is an re match object (from a match of
+# includeRE) and 'dirname' is the directory relative to which the file
+# path should be resolved.
+def replace_include(matchobj, dirname):
+ fname = matchobj.group('filename')
+ full_fname = os.path.normpath(os.path.join(dirname, fname))
+ contents = '##newfile "%s"\n%s\n##endfile\n' % \
+ (full_fname, read_and_flatten(full_fname))
+ return contents
+
+# Read a file and recursively flatten nested '##include' files.
+def read_and_flatten(filename):
+ current_dir = os.path.dirname(filename)
+ try:
+ contents = open(filename).read()
+ except IOError:
+ error(0, 'Error including file "%s"' % filename)
+ fileNameStack.push((filename, 0))
# 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
+ contents = includeRE.sub(lambda m: replace_include(m, current_dir),
+ contents)
+ fileNameStack.pop()
+ return contents
#
# Read in and parse the ISA description.
#
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)
+ # Read file and (recursively) all included files into a string.
+ # PLY requires that the input be in a single string so we have to
+ # do this up front.
+ isa_desc = read_and_flatten(isa_desc_file)
+
+ # Initialize filename stack with outer file.
+ fileNameStack.push((isa_desc_file, 0))
# Parse it.
(isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc)
diff --git a/arch/isa_specific.hh b/arch/isa_specific.hh
index 44f8e9d64..91c9ffb68 100644
--- a/arch/isa_specific.hh
+++ b/arch/isa_specific.hh
@@ -45,7 +45,7 @@
//would treat them as 0 in comparisons.
#define ALPHA_ISA 21064
#define SPARC_ISA 42
-#define MIPS_ISA 1337
+#define MIPS_ISA 34000
//These tell the preprocessor where to find the files of a particular
//ISA, and set the "TheISA" macro for use elsewhere.
diff --git a/arch/mips/SConscript b/arch/mips/SConscript
index b8efa7ef9..ef1ef25d6 100644
--- a/arch/mips/SConscript
+++ b/arch/mips/SConscript
@@ -57,9 +57,9 @@ full_system_sources = Split('''
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
- common_syscall_emul.cc
- linux_process.cc
- tru64_process.cc
+ linux/linux.cc
+ linux/process.cc
+ process.cc
''')
# Set up complete list of sources based on configuration.
diff --git a/arch/mips/faults.cc b/arch/mips/faults.cc
index 142dfe0a4..a31856f07 100644
--- a/arch/mips/faults.cc
+++ b/arch/mips/faults.cc
@@ -27,54 +27,115 @@
*/
#include "arch/mips/faults.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "base/trace.hh"
+
+namespace MipsISA
+{
+
+FaultName MachineCheckFault::_name = "Machine Check";
+FaultVect MachineCheckFault::_vect = 0x0401;
+FaultStat MachineCheckFault::_count;
+
+FaultName AlignmentFault::_name = "Alignment";
+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;
+
+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;
+
+FaultName UnimpFault::_name = "Unimplemented Simulator feature";
+FaultVect UnimpFault::_vect = 0x0001;
+FaultStat UnimpFault::_count;
+
+#if FULL_SYSTEM
+
+void MipsFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ countStat()++;
+
+ // exception restart address
+ if (setRestartAddress() || !xc->inPalMode())
+ xc->setMiscReg(MipsISA::IPR_EXC_ADDR, xc->readPC());
+
+ if (skipFaultingInstruction()) {
+ // traps... skip faulting instruction.
+ xc->setMiscReg(MipsISA::IPR_EXC_ADDR,
+ xc->readMiscReg(MipsISA::IPR_EXC_ADDR) + 4);
+ }
+
+ xc->setPC(xc->readMiscReg(MipsISA::IPR_PAL_BASE) + vect());
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
+}
+
+void ArithmeticFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ panic("Arithmetic traps are unimplemented!");
+}
+
+void UnimpFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ panic("Unimpfault: %s\n", panicStr.c_str());
+}
+
+#endif
+
+} // namespace MipsISA
-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
index c1cb956b0..b0d228090 100644
--- a/arch/mips/faults.hh
+++ b/arch/mips/faults.hh
@@ -30,131 +30,260 @@
#define __MIPS_FAULTS_HH__
#include "sim/faults.hh"
-#include "arch/isa_traits.hh" //For the Addr type
+
+// The design of the "name" and "vect" functions is in sim/faults.hh
+
+namespace MipsISA
+{
+
+typedef const Addr FaultVect;
class MipsFault : public FaultBase
{
+ protected:
+ virtual bool skipFaultingInstruction() {return false;}
+ virtual bool setRestartAddress() {return true;}
public:
- MipsFault(char * newName, int newId, Addr newVect)
- : FaultBase(newName, newId), vect(newVect)
- {;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+ virtual FaultVect vect() = 0;
+ virtual FaultStat & countStat() = 0;
+};
+
+class MachineCheckFault : public MipsFault
+{
+ 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 MipsFault
+{
+ 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;
+}
- Addr vect;
+class ResetFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
};
-extern class ResetFaultType : public MipsFault
+class ArithmeticFault : public MipsFault
{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- ResetFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ResetFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
-extern class ArithmeticFaultType : public MipsFault
+class InterruptFault : public MipsFault
{
+ protected:
+ bool setRestartAddress() {return false;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- ArithmeticFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ArithmeticFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class InterruptFaultType : public MipsFault
+class NDtbMissFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- InterruptFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const InterruptFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class NDtbMissFaultType : public MipsFault
+class PDtbMissFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- NDtbMissFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const NDtbMissFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class PDtbMissFaultType : public MipsFault
+class DtbPageFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- PDtbMissFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const PDtbMissFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class DtbPageFaultType : public MipsFault
+class DtbAcvFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- DtbPageFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const DtbPageFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class DtbAcvFaultType : public MipsFault
+class ItbMissFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- DtbAcvFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const DtbAcvFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class ItbMissFaultType : public MipsFault
+class ItbPageFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- ItbMissFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ItbMissFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class ItbPageFaultType : public MipsFault
+class ItbAcvFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- ItbPageFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ItbPageFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class ItbAcvFaultType : public MipsFault
+class UnimplementedOpcodeFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- ItbAcvFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ItbAcvFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class UnimplementedOpcodeFaultType : public MipsFault
+class FloatEnableFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- UnimplementedOpcodeFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const UnimplementedOpcodeFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class FloatEnableFaultType : public MipsFault
+class PalFault : public MipsFault
{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- FloatEnableFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const FloatEnableFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class PalFaultType : public MipsFault
+class IntegerOverflowFault : public MipsFault
{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- PalFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const PalFault;
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
-extern class IntegerOverflowFaultType : public MipsFault
+class UnimpFault : public MipsFault
{
+ private:
+ std::string panicStr;
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
public:
- IntegerOverflowFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const IntegerOverflowFault;
+ UnimpFault(std::string _str)
+ : panicStr(_str)
+ { }
+
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
-extern Fault ** ListOfFaults[];
-extern int NumFaults;
+} // MipsISA namespace
#endif // __FAULTS_HH__
diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa
index 4125b5101..b2a31c018 100644
--- a/arch/mips/isa/base.isa
+++ b/arch/mips/isa/base.isa
@@ -8,10 +8,6 @@
//Outputs to decoder.hh
output header {{
-#define R31 31
-#include "arch/mips/faults.hh"
-#include "arch/mips/isa_traits.hh"
-
using namespace MipsISA;
@@ -66,27 +62,23 @@ output decoder {{
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)
- {
+ if(_numDestRegs > 0){
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ if(_numSrcRegs > 0) {
+ ss << ",";
printReg(ss, _srcRegIdx[0]);
}
- if(_numSrcRegs > 1)
- {
+ 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]);
+
+ if(mnemonic == "sll" || mnemonic == "sra"){
+ ccprintf(ss,", %d",SA);
}
return ss.str();
diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa
index 58d487ad2..e1124a591 100644
--- a/arch/mips/isa/bitfields.isa
+++ b/arch/mips/isa/bitfields.isa
@@ -26,6 +26,7 @@ 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 RS_SRL <25:22>;
def bitfield RD <15:11>;
@@ -38,7 +39,6 @@ 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>;
@@ -47,6 +47,10 @@ def bitfield SRL <21:21>;
def bitfield SRLV < 6: 6>;
def bitfield SA <10: 6>;
+// Floating Point Condition Codes
+def bitfield CC <10:8>;
+def bitfield BRANCH_CC <20:18>;
+
// CP0 Register Select
def bitfield SEL < 2: 0>;
diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa
index 3f054f6a5..1454aba39 100644
--- a/arch/mips/isa/decoder.isa
+++ b/arch/mips/isa/decoder.isa
@@ -1,4 +1,4 @@
-// -*- mode:c++ -*-
+ // -*- mode:c++ -*-
////////////////////////////////////////////////////////////////////
//
@@ -20,36 +20,53 @@ decode OPCODE_HI default Unknown::unknown() {
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}});
+ 0: movf({{ if (getFPConditionCode(FCSR, CC) == 0) Rd = Rs}});
+ 1: movt({{ if (getFPConditionCode(FCSR, CC) == 1) Rd = Rs}});
}
}
format BasicOp {
//Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields
- //are used to distinguish among the SLL, NOP, SSNOP and EHB functions."
-
- 0x0: 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
- }
- }
+ //are used to distinguish among the SLL, NOP, SSNOP and EHB functions.
+ 0x0: decode RS {
+ 0x0: decode RT { //fix Nop traditional vs. Nop converted disassembly later
+ 0x0: decode RD default Nop::nop(){
+ 0x0: decode SA {
+ 0x1: ssnop({{ ; }}); //really sll r0,r0,1
+ 0x3: ehb({{ ; }}); //really sll r0,r0,3
+ }
+ }
+
+ default: sll({{ Rd = Rt.uw << SA; }});
}
+
}
- 0x2: decode SRL {
- 0: srl({{ Rd = Rt.uw >> SA; }});
+ 0x2: decode RS_SRL {
+ 0x0:decode SRL {
+ 0: srl({{ Rd = Rt.uw >> SA; }});
- //Hardcoded assuming 32-bit ISA, probably need parameter here
- 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}});
+ //Hardcoded assuming 32-bit ISA, probably need parameter here
+ 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}});
+ }
}
- 0x3: sra({{ Rd = Rt.sw >> SA; }});
+ 0x3: decode RS {
+ 0x0: sra({{
+ uint32_t temp = Rt >> SA;
+
+ if ( (Rt & 0x80000000) > 0 ) {
+ uint32_t mask = 0x80000000;
+ for(int i=0; i < SA; i++) {
+ temp |= mask;
+ mask = mask >> 1;
+ }
+ }
+
+ Rd = temp;
+ }});
+ }
0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }});
@@ -60,7 +77,21 @@ decode OPCODE_HI default Unknown::unknown() {
1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}});
}
- 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }});
+ 0x7: srav({{
+ int shift_amt = Rs<4:0>;
+
+ uint32_t temp = Rt >> shift_amt;
+
+ if ( (Rt & 0x80000000) > 0 ) {
+ uint32_t mask = 0x80000000;
+ for(int i=0; i < shift_amt; i++) {
+ temp |= mask;
+ mask = mask >> 1;
+ }
+ }
+
+ Rd = temp;
+ }});
}
}
@@ -76,9 +107,9 @@ decode OPCODE_HI default Unknown::unknown() {
}
0x1: decode HINT {
- 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn);
+ 0: jalr({{ Rd = NNPC; NNPC = Rs; }},IsCall,IsReturn);
- 1: jalr_hb({{ NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn);
+ 1: jalr_hb({{ Rd = NNPC; NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn);
}
}
@@ -87,65 +118,69 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: movn({{ if (Rt != 0) Rd = Rs; }});
}
- format WarnUnimpl {
- 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative
- 0x5: break();
- 0x7: sync();
+ format BasicOp {
+ 0x4: syscall({{ xc->syscall(R2); }},IsNonSpeculative);
+ 0x5: break({{ panic("Not implemented break yet"); }},IsNonSpeculative);
+ 0x7: sync({{ panic("Not implemented sync yet"); }},IsNonSpeculative);
}
}
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); }});
+ 0x0: mfhi({{ Rd = HI; }});
+ 0x1: mthi({{ HI = Rs; }});
+ 0x2: mflo({{ Rd = LO; }});
+ 0x3: mtlo({{ 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>);
+ int64_t temp1 = Rs.sd * Rt.sd;
+ HI = temp1<63:32>;
+ 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>);
+ uint64_t temp1 = Rs.ud * Rt.ud;
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
}});
0x2: div({{
- xc->setMiscReg(Hi,Rs.sw % Rt.sw);
- xc->setMiscReg(Lo,Rs.sw / Rt.sw);
+ HI = Rs.sd % Rt.sd;
+ LO = Rs.sd / Rt.sd;
}});
0x3: divu({{
- xc->setMiscReg(Hi,Rs.uw % Rt.uw);
- xc->setMiscReg(Lo,Rs.uw / Rt.uw);
+ HI = Rs.ud % Rt.ud;
+ LO = Rs.ud / Rt.ud;
}});
}
}
- 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);}});
+ 0x4: decode HINT {
+ 0x0: 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.sw;}});
+ 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}});
+ 0x5: decode HINT {
+ 0x0: 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}});
+ }
}
}
@@ -169,7 +204,6 @@ decode OPCODE_HI default Unknown::unknown() {
}
format BranchLikely {
- //MIPS obsolete instructions
0x2: bltzl({{ cond = (Rs.sw < 0); }});
0x3: bgezl({{ cond = (Rs.sw >= 0); }});
}
@@ -193,7 +227,6 @@ decode OPCODE_HI default Unknown::unknown() {
}
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);
}
@@ -215,8 +248,13 @@ decode OPCODE_HI default Unknown::unknown() {
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); }});
+ 0x6: decode RT {
+ 0x0: blez({{ cond = (Rs.sw <= 0); }});
+ }
+
+ 0x7: decode RT {
+ 0x0: bgtz({{ cond = (Rs.sw > 0); }});
+ }
}
}
@@ -225,11 +263,14 @@ decode OPCODE_HI default Unknown::unknown() {
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}});
+ 0x3: sltiu({{ Rt.uw = ( Rs.uw < (uint32_t)sextImm ) ? 1 : 0 }});
+ 0x4: andi({{ Rt.sw = Rs.sw & zextImm;}});
+ 0x5: ori({{ Rt.sw = Rs.sw | zextImm;}});
+ 0x6: xori({{ Rt.sw = Rs.sw ^ zextImm;}});
+
+ 0x7: decode RS {
+ 0x0: lui({{ Rt = imm << 16}});
+ }
}
}
@@ -258,6 +299,7 @@ decode OPCODE_HI default Unknown::unknown() {
//sel field. In those instances, the sel field must be zero.
//MT Code Needed Here
+
}});
0xC: mttr({{
@@ -283,55 +325,37 @@ decode OPCODE_HI default Unknown::unknown() {
0x0: decode SC {
0x0: dvpe({{
- int idx;
- int sel;
- getMiscRegIdx(MVPControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel);
+ Rt.sw = xc->readMiscReg(MVPControl);
+ xc->setMiscReg(MVPControl,0);
}});
0x1: evpe({{
- int idx;
- int sel;
- getMiscRegIdx(MVPControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel,1);
+ Rt.sw = xc->readMiscReg(MVPControl);
+ xc->setMiscReg(MVPControl,1);
}});
}
0x1: decode SC {
0x0: dmt({{
- int idx;
- int sel;
- getMiscRegIdx(VPEControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel);
+ Rt.sw = xc->readMiscReg(VPEControl);
+ xc->setMiscReg(VPEControl,0);
}});
0x1: emt({{
- int idx;
- int sel;
- getMiscRegIdx(VPEControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel,1);
+ Rt.sw = xc->readMiscReg(VPEControl);
+ xc->setMiscReg(VPEControl,1);
}});
}
0xC: decode SC {
0x0: di({{
- int idx;
- int sel;
- getMiscRegIdx(Status,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel);
+ Rt.sw = xc->readMiscReg(Status);
+ xc->setMiscReg(Status,0);
}});
0x1: ei({{
- int idx;
- int sel;
- getMiscRegIdx(Status,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel,1);
+ Rt.sw = xc->readMiscReg(Status);
+ xc->setMiscReg(Status,1);
}});
}
}
@@ -370,27 +394,91 @@ decode OPCODE_HI default Unknown::unknown() {
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*/}});
+ 0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }});
+ 0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}});
+ 0x4: mtc1 ({{ Fs.uw = Rt.uw; }});
+ 0x7: mthc1({{
+ uint64_t fs_hi = Rt.uw;
+ uint64_t fs_lo = Fs.ud & 0x0000FFFF;
+ Fs.ud = fs_hi << 32 | fs_lo;
+ }});
+ }
+
+ format System {
+ 0x2: cfc1({{
+ switch (FS)
+ {
+ case 0:
+ Rt = FIR;
+ break;
+ case 25:
+ Rt = 0 | (FCSR & 0xFE000000) >> 24 | (FCSR & 0x00800000) >> 23;
+ break;
+ case 26:
+ Rt = 0 | (FCSR & 0x0003F07C);
+ break;
+ case 28:
+ Rt = 0 | (FCSR & 0x00000F80) | (FCSR & 0x01000000) >> 21 | (FCSR & 0x00000003);
+ break;
+ case 31:
+ Rt = FCSR;
+ break;
+ default:
+ panic("FP Control Value (%d) Not Available. Ignoring Access to"
+ "Floating Control Status Register",FS);
+ }
+ }});
+
+ 0x6: ctc1({{
+ switch (FS)
+ {
+ case 25:
+ FCSR = 0 | (Rt.uw<7:1> << 25) // move 31...25
+ | (FCSR & 0x01000000) // bit 24
+ | (FCSR & 0x004FFFFF);// bit 22...0
+ break;
+
+ case 26:
+ FCSR = 0 | (FCSR & 0xFFFC0000) // move 31...18
+ | Rt.uw<17:12> << 12 // bit 17...12
+ | (FCSR & 0x00000F80) << 7// bit 11...7
+ | Rt.uw<6:2> << 2 // bit 6...2
+ | (FCSR & 0x00000002); // bit 1...0
+ break;
+
+ case 28:
+ FCSR = 0 | (FCSR & 0xFE000000) // move 31...25
+ | Rt.uw<2:2> << 24 // bit 24
+ | (FCSR & 0x00FFF000) << 23// bit 23...12
+ | Rt.uw<11:7> << 7 // bit 24
+ | (FCSR & 0x000007E)
+ | Rt.uw<1:0>;// bit 22...0
+ break;
+
+ case 31:
+ FCSR = Rt.uw;
+ break;
+
+ default:
+ panic("FP Control Value (%d) Not Available. Ignoring Access to"
+ "Floating Control Status Register", FS);
+ }
+ }});
}
}
0x1: decode ND {
0x0: decode TF {
format Branch {
- 0x0: bc1f({{ cond = (xc->readMiscReg(FPCR) == 0); }});
- 0x1: bc1t({{ cond = (xc->readMiscReg(FPCR) == 1); }});
+ 0x0: bc1f({{ cond = (getFPConditionCode(FCSR,CC) == 0); }});
+ 0x1: bc1t({{ cond = (getFPConditionCode(FCSR,CC) == 1); }});
}
}
0x1: decode TF {
format BranchLikely {
- 0x0: bc1fl({{ cond = (xc->readMiscReg(FPCR) == 0); }});
- 0x1: bc1tl({{ cond = (xc->readMiscReg(FPCR) == 1); }});
+ 0x0: bc1fl({{ cond = (getFPConditionCode(FCSR,CC) == 0); }});
+ 0x1: bc1tl({{ cond = (getFPConditionCode(FCSR,CC) == 1); }});
}
}
}
@@ -401,164 +489,422 @@ decode OPCODE_HI default Unknown::unknown() {
//Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S
//(( single-word ))
- 0x0: decode RS_HI {
- 0x0: decode RS_LO {
+ 0x0: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_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;}});
+ 0x0: add_s({{ Fd.sf = Fs.sf + Ft.sf;}});
+ 0x1: sub_s({{ Fd.sf = Fs.sf - Ft.sf;}});
+ 0x2: mul_s({{ Fd.sf = Fs.sf * Ft.sf;}});
+ 0x3: div_s({{ Fd.sf = Fs.sf / Ft.sf;}});
+ 0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}});
+ 0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}});
+ 0x6: mov_s({{ Fd.sf = Fs.sf;}});
+ 0x7: neg_s({{ Fd.sf = -1 * Fs.sf;}});
}
}
- 0x1: decode RS_LO {
- //only legal for 64 bit-FP
+ 0x1: decode FUNCTION_LO {
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);}});
+ 0x0: round_l_s({{
+ Fd.ud = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_LONG);
+ }});
+
+ 0x1: trunc_l_s({{
+ Fd.ud = fpConvert(truncFP(Fs.sf), SINGLE_TO_LONG);
+ }});
+
+ 0x2: ceil_l_s({{
+ Fd.ud = fpConvert(ceil(Fs.sf), SINGLE_TO_LONG);
+ }});
+
+ 0x3: floor_l_s({{
+ Fd.ud = fpConvert(floor(Fs.sf), SINGLE_TO_LONG);
+ }});
}
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);}});
+ 0x4: round_w_s({{
+ Fd.uw = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_WORD);
+ }});
+
+ 0x5: trunc_w_s({{
+ Fd.uw = fpConvert(truncFP(Fs.sf), SINGLE_TO_WORD);
+ }});
+
+ 0x6: ceil_w_s({{
+ Fd.uw = fpConvert(ceil(Fs.sf), SINGLE_TO_WORD);
+ }});
+
+ 0x7: floor_w_s({{
+ Fd.uw = fpConvert(floor(Fs.sf), SINGLE_TO_WORD);
+ }});
}
}
- 0x2: decode RS_LO {
+ 0x2: decode FUNCTION_LO {
0x1: decode MOVCF {
format FloatOp {
- 0x0: movfs({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }});
- 0x1: movts({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}});
+ 0x0: movf_s({{if (getFPConditionCode(FCSR,CC) == 0) Fd = Fs;}});
+ 0x1: movt_s({{if (getFPConditionCode(FCSR,CC) == 1) Fd = Fs;}});
}
}
- format BasicOp {
- 0x2: movzs({{ if (Rt == 0) Fd = Fs; }});
- 0x3: movns({{ if (Rt != 0) Fd = Fs; }});
+ format FloatOp {
+ 0x2: movz_s({{ if (Rt == 0) Fd = Fs; }});
+ 0x3: movn_s({{ if (Rt != 0) Fd = Fs; }});
+ 0x5: recip_s({{ Fd = 1 / Fs; }});
+ 0x6: rsqrt_s({{ Fd = 1 / sqrt(Fs);}});
}
+ }
- format Float64Op {
- 0x5: recips({{ Fd = 1 / Fs; }});
- 0x6: rsqrts({{ Fd = 1 / sqrt((double)Fs.ud);}});
+ 0x4: decode FUNCTION_LO {
+
+ format FloatConvertOp {
+ 0x1: cvt_d_s({{
+ Fd.ud = fpConvert(Fs.sf, SINGLE_TO_DOUBLE);
+ }});
+
+ 0x4: cvt_w_s({{
+ Fd.uw = fpConvert(Fs.sf, SINGLE_TO_WORD);
+ }});
+ }
+
+ format FloatConvertOp {
+ 0x5: cvt_l_s({{
+ Fd.ud = fpConvert(Fs.sf, SINGLE_TO_LONG);
+ }});
+
+ 0x6: cvt_ps_st({{
+ Fd.ud = (uint64_t)Fs.uw << 32 | (uint64_t)Ft.uw;
+ }});
}
}
- 0x4: decode RS_LO {
+ 0x6: decode FUNCTION_LO {
+ format FloatCompareOp {
+ 0x0: c_f_s({{ cond = 0; }});
- format FloatOp {
- 0x1: cvt_d_s({{ int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE);
+ 0x1: c_un_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = 0;
}});
- 0x4: cvt_w_s({{ int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE);
+ 0x2: c_eq_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf == Ft.sf);
}});
- }
- //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);
+ 0x3: c_ueq_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = (Fs.sf == Ft.sf);
+ }});
+
+ 0x4: c_olt_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf < Ft.sf);
}});
- 0x6: cvt_ps_s({{ /*Fd.df = Fs.df<31:0> | Ft.df<31:0>;*/ }});
+ 0x5: c_ult_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = (Fs.sf < Ft.sf);
+ }});
+
+ 0x6: c_ole_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf <= Ft.sf);
+ }});
+
+ 0x7: c_ule_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = (Fs.sf <= Ft.sf);
+ }});
+ }
+ }
+
+ 0x7: decode FUNCTION_LO {
+ format FloatCompareWithXcptOp {
+ 0x0: c_sf_s({{ cond = 0; }});
+
+ 0x1: c_ngle_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = 0;
+ }});
+
+ 0x2: c_seq_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf == Ft.sf);
+ }});
+
+ 0x3: c_ngl_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = (Fs.sf == Ft.sf);
+ }});
+
+ 0x4: c_lt_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf < Ft.sf);
+ }});
+
+ 0x5: c_nge_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = (Fs.sf < Ft.sf);
+ }});
+
+ 0x6: c_le_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf <= Ft.sf);
+ }});
+
+ 0x7: c_ngt_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = (Fs.sf <= Ft.sf);
+ }});
}
}
}
//Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D
- 0x1: decode RS_HI {
- 0x0: decode RS_LO {
+ 0x1: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_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;}});
+ 0x0: add_d({{ Fd.df = Fs.df + Ft.df;}});
+ 0x1: sub_d({{ Fd.df = Fs.df - Ft.df;}});
+ 0x2: mul_d({{ Fd.df = Fs.df * Ft.df;}});
+ 0x3: div_d({{ Fd.df = Fs.df / Ft.df;}});
+ 0x4: sqrt_d({{ Fd.df = sqrt(Fs.df);}});
+ 0x5: abs_d({{ Fd.df = fabs(Fs.df);}});
+ 0x6: mov_d({{ Fd.ud = Fs.ud;}});
+ 0x7: neg_d({{ 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);}});
+ 0x1: decode FUNCTION_LO {
+ format FloatOp {
+ 0x0: round_l_d({{
+ Fd.ud = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_LONG);
+ }});
+
+ 0x1: trunc_l_d({{
+ Fd.ud = fpConvert(truncFP(Fs.df), DOUBLE_TO_LONG);
+ }});
+
+ 0x2: ceil_l_d({{
+ Fd.ud = fpConvert(ceil(Fs.df), DOUBLE_TO_LONG);
+ }});
+
+ 0x3: floor_l_d({{
+ Fd.ud = fpConvert(floor(Fs.df), DOUBLE_TO_LONG);
+ }});
}
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); }});
+ 0x4: round_w_d({{
+ Fd.uw = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_WORD);
+ }});
+
+ 0x5: trunc_w_d({{
+ Fd.uw = fpConvert(truncFP(Fs.df), DOUBLE_TO_WORD);
+ }});
+
+ 0x6: ceil_w_d({{
+ Fd.uw = fpConvert(ceil(Fs.df), DOUBLE_TO_WORD);
+ }});
+
+ 0x7: floor_w_d({{
+ Fd.uw = fpConvert(floor(Fs.df), DOUBLE_TO_WORD);
+ }});
}
}
- 0x2: decode RS_LO {
+ 0x2: decode FUNCTION_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; }});
+ 0x0: movf_d({{if (getFPConditionCode(FCSR,CC) == 0) Fd.df = Fs.df; }});
+ 0x1: movt_d({{if (getFPConditionCode(FCSR,CC) == 1) Fd.df = Fs.df; }});
}
}
format BasicOp {
- 0x2: movzd({{ if (Rt == 0) Fd.df = Fs.df; }});
- 0x3: movnd({{ if (Rt != 0) Fd.df = Fs.df; }});
+ 0x2: movz_d({{ if (Rt == 0) Fd.df = Fs.df; }});
+ 0x3: movn_d({{ if (Rt != 0) Fd.df = Fs.df; }});
}
- format Float64Op {
- 0x5: recipd({{ Fd.df = 1 / Fs.df}});
- 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }});
+ format FloatOp {
+ 0x5: recip_d({{ Fd.df = 1 / Fs.df}});
+ 0x6: rsqrt_d({{ Fd.df = 1 / sqrt(Fs.df) }});
}
}
- 0x4: decode RS_LO {
+ 0x4: decode FUNCTION_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);
+ Fd.uw = fpConvert(Fs.df, DOUBLE_TO_SINGLE);
}});
0x4: cvt_w_d({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE);
+ Fd.uw = fpConvert(Fs.df, DOUBLE_TO_WORD);
}});
- }
- //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);
+ Fd.ud = fpConvert(Fs.df, DOUBLE_TO_LONG);
+ }});
+ }
+ }
+
+ 0x6: decode FUNCTION_LO {
+ format FloatCompareOp {
+ 0x0: c_f_d({{ cond = 0; }});
+
+ 0x1: c_un_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = 0;
+ }});
+
+ 0x2: c_eq_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 0;
+ else
+ cond = (Fs.df == Ft.df);
}});
+
+ 0x3: c_ueq_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = (Fs.df == Ft.df);
+ }});
+
+ 0x4: c_olt_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 0;
+ else
+ cond = (Fs.df < Ft.df);
+ }});
+
+ 0x5: c_ult_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = (Fs.df < Ft.df);
+ }});
+
+ 0x6: c_ole_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 0;
+ else
+ cond = (Fs.df <= Ft.df);
+ }});
+
+ 0x7: c_ule_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = (Fs.df <= Ft.df);
+ }});
+ }
+ }
+
+ 0x7: decode FUNCTION_LO {
+ format FloatCompareWithXcptOp {
+ 0x0: c_sf_d({{ cond = 0; }});
+
+ 0x1: c_ngle_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = 0;
+ }});
+
+ 0x2: c_seq_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 0;
+ else
+ cond = (Fs.df == Ft.df);
+ }});
+
+ 0x3: c_ngl_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = (Fs.df == Ft.df);
+ }});
+
+ 0x4: c_lt_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 0;
+ else
+ cond = (Fs.df < Ft.df);
+ }});
+
+ 0x5: c_nge_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = (Fs.df < Ft.df);
+ }});
+
+ 0x6: c_le_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 0;
+ else
+ cond = (Fs.df <= Ft.df);
+ }});
+
+ 0x7: c_ngt_d({{
+ if (isnan(Fs.df) || isnan(Ft.df))
+ cond = 1;
+ else
+ cond = (Fs.df <= Ft.df);
+ }});
}
}
}
//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);
+ format FloatConvertOp {
+ 0x20: cvt_s_w({{
+ Fd.uw = fpConvert(Fs.sf, WORD_TO_SINGLE);
+ }});
+
+ 0x21: cvt_d_w({{
+ Fd.ud = fpConvert(Fs.sf, WORD_TO_DOUBLE);
}});
+ }
- 0x21: cvt_d({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_WORD);
+ format Float64ConvertOp {
+ 0x26: cvt_ps_pw({{
+ Fd.ud = fpConvert(Fs.ud, WORD_TO_PS);
}});
}
}
@@ -567,15 +913,17 @@ decode OPCODE_HI default Unknown::unknown() {
//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);
+ format Float64ConvertOp {
+ 0x20: cvt_s_l({{
+ Fd.uw = fpConvert(Fs.ud, LONG_TO_SINGLE);
+ }});
+
+ 0x21: cvt_d_l({{
+ Fd.ud = fpConvert(Fs.ud, LONG_TO_DOUBLE);
}});
- 0x11: cvt_d_l({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_LONG);
+ 0x26: cvt_ps_l({{
+ Fd.ud = fpConvert(Fs.ud, LONG_TO_PS);
}});
}
}
@@ -583,73 +931,275 @@ decode OPCODE_HI default Unknown::unknown() {
//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 {
+ 0x6: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_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;
+ 0x0: add_ps({{
+ Fd1.sf = Fs1.sf + Ft2.sf;
+ Fd2.sf = Fs2.sf + Ft2.sf;
}});
- 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = Fs.df - Ft.df;
+ 0x1: sub_ps({{
+ Fd1.sf = Fs1.sf - Ft2.sf;
+ Fd2.sf = Fs2.sf - Ft2.sf;
}});
- 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = Fs.df * Ft.df;
+ 0x2: mul_ps({{
+ Fd1.sf = Fs1.sf * Ft2.sf;
+ Fd2.sf = Fs2.sf * Ft2.sf;
}});
- 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);
+ 0x5: abs_ps({{
+ Fd1.sf = fabs(Fs1.sf);
+ Fd2.sf = fabs(Fs2.sf);
}});
- 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- //Fd.df = Fs<31:0> | Ft<31:0>;
+ 0x6: mov_ps({{
+ Fd1.sf = Fs1.sf;
+ Fd2.sf = Fs2.sf;
}});
- 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = -1 * Fs.df;
+ 0x7: neg_ps({{
+ Fd1.sf = -1 * Fs1.sf;
+ Fd2.sf = -1 * Fs2.sf;
}});
}
}
- 0x2: decode RS_LO {
+ 0x2: decode FUNCTION_LO {
0x1: decode MOVCF {
format Float64Op {
- 0x0: movfps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs;}});
- 0x1: movtps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}});
+ 0x0: movf_ps({{
+ if (getFPConditionCode(FCSR, CC) == 0)
+ Fd1 = Fs1;
+ if (getFPConditionCode(FCSR, CC+1) == 0)
+ Fd2 = Fs2;
+ }});
+
+ 0x1: movt_ps({{
+ if (getFPConditionCode(FCSR, CC) == 1)
+ Fd1 = Fs1;
+ if (getFPConditionCode(FCSR, CC+1) == 1)
+ Fd2 = Fs2;
+ }});
}
}
- format BasicOp {
- 0x2: movzps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }});
- 0x3: movnps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs; }});
+ format Float64Op {
+ 0x2: movz_ps({{
+ if (getFPConditionCode(FCSR, CC) == 0)
+ Fd1 = Fs1;
+ if (getFPConditionCode(FCSR, CC) == 0)
+ Fd2 = Fs2;
+ }});
+
+ 0x3: movn_ps({{
+ if (getFPConditionCode(FCSR, CC) == 1)
+ Fd1 = Fs1;
+ if (getFPConditionCode(FCSR, CC) == 1)
+ Fd2 = Fs2;
+ }});
}
}
- 0x4: decode RS_LO {
+ 0x4: decode FUNCTION_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);
+ Fd.uw = fpConvert(Fs2.uw, PU_TO_SINGLE);
}});
}
- 0x5: decode RS_LO {
+ 0x5: decode FUNCTION_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);
+ Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE);
}});
- 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>*/}});
+
+ 0x4: pll({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft1.uw; }});
+ 0x5: plu({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft2.uw; }});
+ 0x6: pul({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft1.uw; }});
+ 0x7: puu({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft2.uw; }});
+ }
+ }
+
+ 0x6: decode FUNCTION_LO {
+ format FloatPSCompareOp {
+ 0x0: c_f_ps({{ cond1 = 0; cond2 = 0; }});
+
+ 0x1: c_un_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = 0;
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = 0;
+
+ }});
+
+ 0x2: c_eq_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x3: c_ueq_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x4: c_olt_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf < Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x5: c_ult_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs.sf < Ft.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x6: c_ole_ps({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs.sf <= Ft.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
+
+ 0x7: c_ule_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf <= Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
+ }
+ }
+
+ 0x7: decode FUNCTION_LO {
+ format FloatPSCompareWithXcptOp {
+ 0x0: c_sf_ps({{ cond1 = 0; cond2 = 0; }});
+
+ 0x1: c_ngle_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = 0;
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = 0;
+ }});
+
+ 0x2: c_seq_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x3: c_ngl_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf == Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf == Ft2.sf);
+ }});
+
+ 0x4: c_lt_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf < Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x5: c_nge_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf < Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf < Ft2.sf);
+ }});
+
+ 0x6: c_le_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 0;
+ else
+ cond1 = (Fs1.sf <= Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 0;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
+
+ 0x7: c_ngt_ps({{
+ if (isnan(Fs1.sf) || isnan(Ft1.sf))
+ cond1 = 1;
+ else
+ cond1 = (Fs1.sf <= Ft1.sf);
+
+ if (isnan(Fs2.sf) || isnan(Ft2.sf))
+ cond2 = 1;
+ else
+ cond2 = (Fs2.sf <= Ft2.sf);
+ }});
}
}
}
@@ -694,24 +1244,18 @@ decode OPCODE_HI default Unknown::unknown() {
//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; */}});
+ format LoadFloatMemory {
+ 0x0: lwxc1({{ Ft.uw = Mem.uw;}}, {{ EA = Rs + Rt; }});
+ 0x1: ldxc1({{ Ft.ud = Mem.ud;}}, {{ EA = Rs + Rt; }});
+ 0x5: luxc1({{ Ft.uw = Mem.ud;}}, {{ EA = Rs + Rt; }});
}
}
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>;*/}});
+ format StoreFloatMemory {
+ 0x0: swxc1({{ Mem.uw = Ft.uw;}}, {{ EA = Rs + Rt; }});
+ 0x1: sdxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }});
+ 0x5: suxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }});
}
0x7: WarnUnimpl::prefx();
@@ -722,49 +1266,44 @@ decode OPCODE_HI default Unknown::unknown() {
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; }});
+ 0x0: madd_s({{ Fd.sf = (Fs.sf * Ft.sf) + Fr.sf; }});
+ 0x1: madd_d({{ Fd.df = (Fs.df * Ft.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;
+ Fd1.sf = (Fs1.df * Ft1.df) + Fr1.df;
+ Fd2.sf = (Fs2.df * Ft2.df) + Fr2.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; }});
+ 0x0: msub_s({{ Fd.sf = (Fs.sf * Ft.sf) - Fr.sf; }});
+ 0x1: msub_d({{ Fd.df = (Fs.df * Ft.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;
+ Fd1.sf = (Fs1.df * Ft1.df) - Fr1.df;
+ Fd2.sf = (Fs2.df * Ft2.df) - Fr2.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; }});
+ 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }});
+ 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.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;
+ Fd1.sf = -1 * ((Fs1.df * Ft1.df) + Fr1.df);
+ Fd2.sf = -1 * ((Fs2.df * Ft2.df) + Fr2.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; }});
+ 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }});
+ 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.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;
+ Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df);
+ Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df);
}});
}
}
}
}
- //MIPS obsolete instructions
format BranchLikely {
0x4: beql({{ cond = (Rs.sw == 0); }});
0x5: bnel({{ cond = (Rs.sw != 0); }});
@@ -781,59 +1320,63 @@ decode OPCODE_HI default Unknown::unknown() {
0x0: decode FUNCTION_LO {
format IntOp {
0x0: madd({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ int64_t temp1 = (int64_t) HI << 32 | LO;
temp1 = temp1 + (Rs.sw * Rt.sw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
0x1: maddu({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ int64_t temp1 = (int64_t) HI << 32 | LO;
temp1 = temp1 + (Rs.uw * Rt.uw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
+ HI = temp1<63:32>;
+ 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;
+ int64_t temp1 = (int64_t) HI << 32 | LO;
temp1 = temp1 - (Rs.sw * Rt.sw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
0x5: msubu({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
+ int64_t temp1 = (int64_t) HI << 32 | LO;
temp1 = temp1 - (Rs.uw * Rt.uw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
+ HI = temp1<63:32>;
+ 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--;
+ int cnt = 0;
+ uint32_t mask = 0x80000000;
+ for (int i=0; i < 32; i++) {
+ if( (Rs & mask) == 0) {
+ cnt++;
+ } else {
+ break;
+ }
}
-
- Rd.uw = cnt;*/
+ Rd.uw = cnt;
}});
0x1: clo({{
- /*int cnt = 0;
- int idx = 0;
- while ( Rs.uw<idx> != 0) {
- cnt++;
- idx--;
+ int cnt = 0;
+ uint32_t mask = 0x80000000;
+ for (int i=0; i < 32; i++) {
+ if( (Rs & mask) != 0) {
+ cnt++;
+ } else {
+ break;
+ }
}
-
- Rd.uw = cnt;*/
+ Rd.uw = cnt;
}});
}
}
@@ -847,14 +1390,14 @@ decode OPCODE_HI default Unknown::unknown() {
0x7: decode FUNCTION_HI {
0x0: decode FUNCTION_LO {
- format WarnUnimpl {
+ format FailUnimpl {
0x1: ext();
0x4: ins();
}
}
0x1: decode FUNCTION_LO {
- format WarnUnimpl {
+ format FailUnimpl {
0x0: fork();
0x1: yield();
}
@@ -864,16 +1407,16 @@ decode OPCODE_HI default Unknown::unknown() {
//Table A-10 MIPS32 BSHFL Encoding of sa Field
0x4: decode SA {
- 0x02: WarnUnimpl::wsbh();
+ 0x02: FailUnimpl::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>}});
+ 0x10: seb({{ Rd.sw = Rt.sw<7:0>}});
+ 0x18: seh({{ Rd.sw = Rt.sw<15:0>}});
}
}
0x6: decode FUNCTION_LO {
- 0x7: BasicOp::rdhwr({{ /*Rt = xc->hwRegs[RD];*/ }});
+ 0x7: FailUnimpl::rdhwr();//{{ /*Rt = xc->hwRegs[RD];*/ }}
}
}
}
@@ -882,23 +1425,238 @@ decode OPCODE_HI default Unknown::unknown() {
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; }});
+
+ 0x2: lwl({{
+ uint32_t mem_word = Mem.uw;
+ uint32_t unalign_addr = Rs + disp;
+ uint32_t offset = unalign_addr & 0x00000003;
+#if BYTE_ORDER == BIG_ENDIAN
+ switch(offset)
+ {
+ case 0:
+ Rt = mem_word;
+ break;
+
+ case 1:
+ Rt &= 0x000F;
+ Rt |= (mem_word << 4);
+ break;
+
+ case 2:
+ Rt &= 0x00FF;
+ Rt |= (mem_word << 8);
+ break;
+
+ case 3:
+ Rt &= 0x0FFF;
+ Rt |= (mem_word << 12);
+ break;
+
+ default:
+ panic("lwl: bad offset");
+ }
+#elif BYTE_ORDER == LITTLE_ENDIAN
+ switch(offset)
+ {
+ case 0:
+ Rt &= 0x0FFF;
+ Rt |= (mem_word << 12);
+ break;
+
+ case 1:
+ Rt &= 0x00FF;
+ Rt |= (mem_word << 8);
+ break;
+
+ case 2:
+ Rt &= 0x000F;
+ Rt |= (mem_word << 4);
+ break;
+
+ case 3:
+ Rt = mem_word;
+ break;
+
+ default:
+ panic("lwl: bad offset");
+ }
+#endif
+ }}, {{ EA = (Rs + disp) & ~3; }});
+
+ 0x3: lw({{ Rt.sw = Mem.sw; }});
0x4: lbu({{ Rt.uw = Mem.ub; }});
0x5: lhu({{ Rt.uw = Mem.uh; }});
- 0x6: lwr({{ Rt.uw = Mem.uw; }});//, WordAlign);
+ 0x6: lwr({{
+ uint32_t mem_word = Mem.uw;
+ uint32_t unalign_addr = Rs + disp;
+ uint32_t offset = unalign_addr & 0x00000003;
+
+#if BYTE_ORDER == BIG_ENDIAN
+ switch(offset)
+ {
+ case 0: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break;
+ case 1: Rt &= 0xFF00; Rt |= (mem_word >> 8); break;
+ case 2: Rt &= 0xF000; Rt |= (mem_word >> 4); break;
+ case 3: Rt = mem_word; break;
+ default: panic("lwr: bad offset");
+ }
+#elif BYTE_ORDER == LITTLE_ENDIAN
+ switch(offset)
+ {
+ case 0: Rt = mem_word; break;
+ case 1: Rt &= 0xF000; Rt |= (mem_word >> 4); break;
+ case 2: Rt &= 0xFF00; Rt |= (mem_word >> 8); break;
+ case 3: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break;
+ default: panic("lwr: bad offset");
+ }
+#endif
+ }},
+ {{ EA = (Rs + disp) & ~3; }});
}
-
- 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);
+ 0x2: swl({{
+ uint32_t mem_word = 0;
+ uint32_t aligned_addr = (Rs + disp) & ~3;
+ uint32_t unalign_addr = Rs + disp;
+ uint32_t offset = unalign_addr & 0x00000003;
+
+ DPRINTF(IEW,"Execute: aligned=0x%x unaligned=0x%x\n offset=0x%x",
+ aligned_addr,unalign_addr,offset);
+
+ fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags);
+
+#if BYTE_ORDER == BIG_ENDIAN
+ switch(offset)
+ {
+ case 0:
+ Mem = Rt;
+ break;
+
+ case 1:
+ mem_word &= 0xF000;
+ mem_word |= (Rt >> 4);
+ Mem = mem_word;
+ break;
+
+ case 2:
+ mem_word &= 0xFF00;
+ mem_word |= (Rt >> 8);
+ Mem = mem_word;
+ break;
+
+ case 3:
+ mem_word &= 0xFFF0;
+ mem_word |= (Rt >> 12);
+ Mem = mem_word;
+ break;
+
+ default:
+ panic("swl: bad offset");
+ }
+#elif BYTE_ORDER == LITTLE_ENDIAN
+ switch(offset)
+ {
+ case 0:
+ mem_word &= 0xFFF0;
+ mem_word |= (Rt >> 12);
+ Mem = mem_word;
+ break;
+
+ case 1:
+ mem_word &= 0xFF00;
+ mem_word |= (Rt >> 8);
+ Mem = mem_word;
+ break;
+
+ case 2:
+ mem_word &= 0xF000;
+ mem_word |= (Rt >> 4);
+ Mem = mem_word;
+ break;
+
+ case 3:
+ Mem = Rt;
+ break;
+
+ default:
+ panic("swl: bad offset");
+ }
+#endif
+ }},{{ EA = (Rs + disp) & ~3; }},mem_flags = NO_ALIGN_FAULT);
+
+ 0x3: sw({{ Mem.uw = Rt<31:0>; }});
+
+ 0x6: swr({{
+ uint32_t mem_word = 0;
+ uint32_t aligned_addr = (Rs + disp) & ~3;
+ uint32_t unalign_addr = Rs + disp;
+ uint32_t offset = unalign_addr & 0x00000003;
+
+ fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags);
+
+#if BYTE_ORDER == BIG_ENDIAN
+ switch(offset)
+ {
+ case 0:
+ mem_word &= 0x0FFF;
+ mem_word |= (Rt << 12);
+ Mem = mem_word;
+ break;
+
+ case 1:
+ mem_word &= 0x00FF;
+ mem_word |= (Rt << 8);
+ Mem = mem_word;
+ break;
+
+ case 2:
+ mem_word &= 0x000F;
+ mem_word |= (Rt << 4);
+ Mem = mem_word;
+ break;
+
+ case 3:
+ Mem = Rt;
+ break;
+
+ default:
+ panic("swr: bad offset");
+ }
+#elif BYTE_ORDER == LITTLE_ENDIAN
+ switch(offset)
+ {
+ case 0:
+ Mem = Rt;
+ break;
+
+ case 1:
+ mem_word &= 0x000F;
+ mem_word |= (Rt << 4);
+ Mem = mem_word;
+ break;
+
+ case 2:
+ mem_word &= 0x00FF;
+ mem_word |= (Rt << 8);
+ Mem = mem_word;
+ break;
+
+ case 3:
+ mem_word &= 0x0FFF;
+ mem_word |= (Rt << 12);
+ Mem = mem_word;
+ break;
+
+ default:
+ panic("swr: bad offset");
+ }
+#endif
+ }},{{ EA = (Rs + disp) & ~3;}},mem_flags = NO_ALIGN_FAULT);
}
format WarnUnimpl {
@@ -908,21 +1666,21 @@ decode OPCODE_HI default Unknown::unknown() {
}
0x6: decode OPCODE_LO default FailUnimpl::reserved() {
- 0x0: WarnUnimpl::ll();
+ 0x0: LoadMemory::ll({{Rt.uw = Mem.uw}},mem_flags=LOCKED);
- format LoadMemory {
- 0x1: lwc1({{ /*F_t<31:0> = Mem.sf; */}});
- 0x5: ldc1({{ /*F_t<63:0> = Mem.df; */}});
+ format LoadFloatMemory {
+ 0x1: lwc1({{ Ft.uw = Mem.uw; }});
+ 0x5: ldc1({{ Ft.ud = Mem.ud; }});
}
}
0x7: decode OPCODE_LO default FailUnimpl::reserved() {
- 0x0: WarnUnimpl::sc();
+ 0x0: StoreMemory::sc({{ Mem.uw = Rt.uw; Rt.uw = 1; }});
- format StoreMemory {
- 0x1: swc1({{ //Mem.sf = Ft<31:0>; }});
- 0x5: sdc1({{ //Mem.df = Ft<63:0>; }});
+ format StoreFloatMemory {
+ 0x1: swc1({{ Mem.uw = Ft.uw; }});
+ 0x5: sdc1({{ Mem.ud = Ft.ud; }});
}
}
}
diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa
deleted file mode 100644
index f7a9e4ce2..000000000
--- a/arch/mips/isa/formats.isa
+++ /dev/null
@@ -1,35 +0,0 @@
-// -*- 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/branch.isa b/arch/mips/isa/formats/branch.isa
index 0d2ad7855..8cfa37a20 100644
--- a/arch/mips/isa/formats/branch.isa
+++ b/arch/mips/isa/formats/branch.isa
@@ -179,7 +179,7 @@ output decoder {{
ss << ",";
}
- Addr target = pc + 8 + disp;
+ Addr target = pc + 4 + disp;
std::string str;
if (symtab && symtab->findSymbol(target, str))
@@ -187,6 +187,12 @@ output decoder {{
else
ccprintf(ss, "0x%x", target);
+ string inst_name = mnemonic;
+
+ if (inst_name.substr(inst_name.length()-2,inst_name.length()) == "al"){
+ ccprintf(ss, " (r31=0x%x)",pc+8);
+ }
+
return ss.str();
}
@@ -255,7 +261,7 @@ def format Branch(code,*flags) {{
#Add Link Code if Link instruction
strlen = len(name)
if name[strlen-2:] == 'al':
- code += 'r31 = NNPC;\n'
+ code += 'R31 = NNPC;\n'
#Condition code
code = 'bool cond;\n' + code
@@ -265,8 +271,6 @@ def format Branch(code,*flags) {{
code += ' NNPC = NNPC;\n'
code += '} \n'
- code += 'cout << hex << "NPC: " << NPC << " + " << disp << " = " << NNPC << endl;'
-
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
('IsDirectControl', 'IsCondControl'))
@@ -281,7 +285,7 @@ def format BranchLikely(code,*flags) {{
#Add Link Code if Link instruction
strlen = len(name)
if name[strlen-3:] == 'all':
- code += 'r31 = NNPC;\n'
+ code += 'R31 = NNPC;\n'
#Condition code
code = 'bool cond;\n' + code
@@ -303,10 +307,8 @@ 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 = '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'))
diff --git a/arch/mips/isa/formats/formats.isa b/arch/mips/isa/formats/formats.isa
new file mode 100644
index 000000000..7d493ffae
--- /dev/null
+++ b/arch/mips/isa/formats/formats.isa
@@ -0,0 +1,35 @@
+// -*- mode:c++ -*-
+
+//Templates from this format are used later
+//Include the basic format
+##include "basic.isa"
+
+//Include the basic format
+##include "noop.isa"
+
+//Include utility functions
+##include "util.isa"
+
+//Include the cop0 formats
+##include "cop0.isa"
+
+//Include the integer formats
+##include "int.isa"
+
+//Include the floatOp format
+##include "fp.isa"
+
+//Include the mem format
+##include "mem.isa"
+
+//Include the trap format
+##include "trap.isa"
+
+//Include the branch format
+##include "branch.isa"
+
+//Include the noop format
+##include "unimp.isa"
+
+//Include the noop format
+##include "unknown.isa"
diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa
index 34b71acf7..9f2c24755 100644
--- a/arch/mips/isa/formats/fp.isa
+++ b/arch/mips/isa/formats/fp.isa
@@ -30,7 +30,7 @@ output decoder {{
}};
-// Primary format for integer operate instructions:
+// Primary format for float operate instructions:
def format FloatOp(code, *flags) {{
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
header_output = BasicDeclare.subst(iop)
@@ -39,7 +39,35 @@ def format FloatOp(code, *flags) {{
exec_output = BasicExecute.subst(iop)
}};
-// Primary format for integer operate instructions:
+def format FloatCompareOp(code, *flags) {{
+ code = 'bool cond;\n' + code
+ code += 'FCSR = makeCCVector(FCSR, CC,cond);\n'
+ 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)
+}};
+
+def format FloatCompareWithXcptOp(code, *flags) {{
+ code = 'bool cond;\n' + code
+ code += 'FCSR = makeCCVector(FCSR, CC,cond);\n'
+ 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)
+}};
+
+def format FloatConvertOp(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 float64 operate instructions:
def format Float64Op(code, *flags) {{
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
header_output = BasicDeclare.subst(iop)
@@ -47,3 +75,35 @@ def format Float64Op(code, *flags) {{
decode_block = BasicDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
+
+def format Float64ConvertOp(code, *flags) {{
+ code = 'bool cond;\n' + code
+ code += 'FCSR = makeCCVector(FCSR, CC,cond);\n'
+ 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)
+}};
+
+def format FloatPSCompareOp(code, *flags) {{
+ code = 'bool cond1;\nbool cond2;\n' + code
+ code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n'
+ code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n'
+ 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)
+}};
+
+def format FloatPSCompareWithXcptOp(code, *flags) {{
+ code = 'bool cond1;\nbool cond2;\n' + code
+ code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n'
+ code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n'
+ 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
index a47844bee..7d38b9ff5 100644
--- a/arch/mips/isa/formats/int.isa
+++ b/arch/mips/isa/formats/int.isa
@@ -29,17 +29,19 @@ output header {{
{
protected:
- int32_t imm;
+ int16_t imm;
+ int32_t sextImm;
+ uint32_t zextImm;
/// Constructor
IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
- MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM)
+ MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM),
+ sextImm(INTIMM),zextImm(0x0000FFFF & INTIMM)
{
//If Bit 15 is 1 then Sign Extend
- int32_t temp = imm & 0x00008000;
-
+ int32_t temp = sextImm & 0x00008000;
if (temp > 0 && mnemonic != "lui") {
- imm |= 0xFFFF0000;
+ sextImm |= 0xFFFF0000;
}
}
@@ -62,10 +64,9 @@ output decoder {{
// it's generally implicit
if (_numDestRegs > 0) {
printReg(ss, _destRegIdx[0]);
+ ss << ",";
}
- 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
@@ -99,9 +100,9 @@ output decoder {{
}
if( mnemonic == "lui")
- ccprintf(ss, "%08p ", imm);
+ ccprintf(ss, "%08p ", sextImm);
else
- ss << (int) imm;
+ ss << (int) sextImm;
return ss.str();
}
diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa
index 8a07e63d4..e2afc7252 100644
--- a/arch/mips/isa/formats/mem.isa
+++ b/arch/mips/isa/formats/mem.isa
@@ -276,8 +276,7 @@ def template LoadCompleteAcc {{
Fault fault = NoFault;
%(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
+ %(op_decl)s;
memcpy(&Mem, data, sizeof(Mem));
@@ -375,8 +374,7 @@ def template StoreInitiateAcc {{
uint64_t write_result = 0;
%(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
+ %(op_decl)s;
%(op_rd)s;
%(ea_code)s;
@@ -449,21 +447,27 @@ def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
}};
//FP loads are offloaded to these formats for now ...
-def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }},
- mem_flags = [], inst_flags = []) {{
+def format LoadFloatMemory(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,
+ decode_template = BasicDecode,
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 = []) {{
+def format StoreFloatMemory(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 = 'Store')
}};
+
+def format UnalignedStore(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')
+}};
diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa
index d35179005..2aa4816e3 100644
--- a/arch/mips/isa/formats/noop.isa
+++ b/arch/mips/isa/formats/noop.isa
@@ -88,3 +88,7 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
exec_output = BasicExecute.subst(iop)
}};
+def format Nop() {{
+ decode_block = 'return new Nop(\"sll r0,r0,0\",machInst);\n'
+}};
+
diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa
index adbd5b5b1..475a88752 100644
--- a/arch/mips/isa/formats/unimp.isa
+++ b/arch/mips/isa/formats/unimp.isa
@@ -110,8 +110,9 @@ output exec {{
Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
- return UnimplementedOpcodeFault;
+ "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
+ inst2string(machInst));
+ return new UnimplementedOpcodeFault;
}
Fault
diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa
index 4601b3684..ba83c007e 100644
--- a/arch/mips/isa/formats/unknown.isa
+++ b/arch/mips/isa/formats/unknown.isa
@@ -26,12 +26,34 @@
// (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 {{
+ std::string inst2string(MachInst machInst);
+}};
output decoder {{
+
+std::string inst2string(MachInst machInst)
+{
+ string str = "";
+ uint32_t mask = 0x80000000;
+
+ for(int i=0; i < 32; i++) {
+ if ((machInst & mask) == 0) {
+ str += "0";
+ } else {
+ str += "1";
+ }
+
+ mask = mask >> 1;
+ }
+
+ return str;
+}
+
std::string
Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
- return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
- "unknown", machInst, OPCODE);
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)",
+ "unknown", machInst, OPCODE, inst2string(machInst));
}
}};
@@ -41,8 +63,8 @@ output exec {{
Trace::InstRecord *traceData) const
{
panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return UnimplementedOpcodeFault;
+ "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst));
+ return new UnimplementedOpcodeFault;
}
}};
diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa
index db4bf204a..615160931 100644
--- a/arch/mips/isa/formats/util.isa
+++ b/arch/mips/isa/formats/util.isa
@@ -93,8 +93,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
output exec {{
-using namespace MipsISA;
-
+ using namespace MipsISA;
/// CLEAR ALL CPU INST/EXE HAZARDS
inline void
@@ -124,25 +123,7 @@ using namespace MipsISA;
}
#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
index da919be00..9c370fbe3 100644
--- a/arch/mips/isa/includes.isa
+++ b/arch/mips/isa/includes.isa
@@ -9,21 +9,28 @@ output header {{
#include <iomanip>
#include "cpu/static_inst.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
+#include "arch/mips/isa_traits.hh"
}};
output decoder {{
+#include "arch/mips/isa_traits.hh"
#include "base/cprintf.hh"
#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh" // for Jump::branchTarget()
+#include "arch/mips/faults.hh"
+#include "arch/mips/isa_traits.hh"
#include <math.h>
#if defined(linux)
#include <fenv.h>
#endif
+
+using namespace MipsISA;
}};
output exec {{
+#include "arch/mips/faults.hh"
+#include "arch/mips/isa_traits.hh"
#include <math.h>
#if defined(linux)
#include <fenv.h>
@@ -35,5 +42,7 @@ output exec {{
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "sim/sim_exit.hh"
+
+using namespace MipsISA;
}};
diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa
index 411e398b4..01d81323e 100644
--- a/arch/mips/isa/main.isa
+++ b/arch/mips/isa/main.isa
@@ -26,7 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-##include "m5/arch/mips/isa/includes.isa"
+##include "includes.isa"
////////////////////////////////////////////////////////////////////
//
@@ -37,16 +37,16 @@
namespace MipsISA;
//Include the bitfield definitions
-##include "m5/arch/mips/isa/bitfields.isa"
+##include "bitfields.isa"
//Include the operand_types and operand definitions
-##include "m5/arch/mips/isa/operands.isa"
+##include "operands.isa"
//Include the base class for mips instructions, and some support code
-##include "m5/arch/mips/isa/base.isa"
+##include "base.isa"
//Include the definitions for the instruction formats
-##include "m5/arch/mips/isa/formats.isa"
+##include "formats/formats.isa"
//Include the decoder definition
-##include "m5/arch/mips/isa/decoder.isa"
+##include "decoder.isa"
diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa
index 13870337b..0f9c74b48 100644
--- a/arch/mips/isa/operands.isa
+++ b/arch/mips/isa/operands.isa
@@ -13,21 +13,49 @@ def operand_types {{
}};
def operands {{
+ #General Purpose Integer Reg 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),
+ #Operands used for Link or Syscall Insts
+ 'R31': ('IntReg', 'uw','31','IsInteger', 4),
+ 'R2': ('IntReg', 'uw','2', 'IsInteger', 5),
+
+ #Special Integer Reg operands
+ 'HI': ('IntReg', 'uw','32', 'IsInteger', 6),
+ 'LO': ('IntReg', 'uw','33', 'IsInteger', 7),
+
+ #Immediate Value operand
'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
+ #Floating Point Reg Operands
'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),
+ #Special Floating Point Control Reg Operands
+ 'FIR': ('FloatReg', 'uw', '32', 'IsFloating', 1),
+ 'FCCR': ('FloatReg', 'uw', '33', 'IsFloating', 2),
+ 'FEXR': ('FloatReg', 'uw', '34', 'IsFloating', 3),
+ 'FENR': ('FloatReg', 'uw', '35', 'IsFloating', 3),
+ 'FCSR': ('FloatReg', 'uw', '36', 'IsFloating', 3),
+
+ #Operands For Paired Singles FP Operations
+ 'Fd1': ('FloatReg', 'sf', 'FD', 'IsFloating', 4),
+ 'Fd2': ('FloatReg', 'sf', 'FD+1', 'IsFloating', 4),
+ 'Fs1': ('FloatReg', 'sf', 'FS', 'IsFloating', 5),
+ 'Fs2': ('FloatReg', 'sf', 'FS+1', 'IsFloating', 5),
+ 'Ft1': ('FloatReg', 'sf', 'FT', 'IsFloating', 6),
+ 'Ft2': ('FloatReg', 'sf', 'FT+1', 'IsFloating', 6),
+ 'Fr1': ('FloatReg', 'sf', 'FR', 'IsFloating', 7),
+ 'Fr2': ('FloatReg', 'sf', 'FR+1', 'IsFloating', 7),
+
+ #Memory Operand
+ 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ #Program Counter Operands
'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
index d01fa6bd4..216a6e2ec 100644
--- a/arch/mips/isa_traits.cc
+++ b/arch/mips/isa_traits.cc
@@ -30,296 +30,109 @@
#include "config/full_system.hh"
#include "cpu/static_inst.hh"
#include "sim/serialize.hh"
+#include "base/bitfield.hh"
using namespace MipsISA;
+using namespace std;
-//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)
+MipsISA::copyRegs(ExecContext *src, ExecContext *dest)
{
- 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;
+ /*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
+ uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
+ lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
+ lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag);
- default:
- panic("Accessing Unimplemented Misc. Register");
- }
+#if FULL_SYSTEM
+ copyIprs(xc);
+ #endif*/
}
-void RegFile::coldReset()
+void
+MipsISA::MiscRegFile::copyMiscRegs(ExecContext *xc)
{
- //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;
+ /*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
+ uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
+ lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
+ lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag);
+ #endif*/
}
-void RegFile::createCP0Regs()
+uint64_t
+MipsISA::fpConvert(double fp_val, ConvertType cvt_type)
{
-//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);
+ switch (cvt_type)
+ {
+ case SINGLE_TO_DOUBLE:
+ double sdouble_val = fp_val;
+ void *sdouble_ptr = &sdouble_val;
+ uint64_t sdp_bits = *(uint64_t *) sdouble_ptr;
+ return sdp_bits;
+
+ case SINGLE_TO_WORD:
+ int32_t sword_val = (int32_t) fp_val;
+ void *sword_ptr = &sword_val;
+ uint64_t sword_bits= *(uint32_t *) sword_ptr;
+ return sword_bits;
+
+ case WORD_TO_SINGLE:
+ float wfloat_val = fp_val;
+ void *wfloat_ptr = &wfloat_val;
+ uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr;
+ return wfloat_bits;
+
+ case WORD_TO_DOUBLE:
+ double wdouble_val = fp_val;
+ void *wdouble_ptr = &wdouble_val;
+ uint64_t wdp_bits = *(uint64_t *) wdouble_ptr;
+ return wdp_bits;
- //Cop-0 Regs. Bank 26:
- miscRegs[26].resize(1);
+ default:
+ panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type);
+ return 0;
+ }
+}
- //Cop-0 Regs. Bank 27:
- miscRegs[27].resize(4);
+double
+MipsISA::roundFP(double val, int digits)
+{
+ double digit_offset = pow(10.0,digits);
+ val = val * digit_offset;
+ val = val + 0.5;
+ val = floor(val);
+ val = val / digit_offset;
+ return val;
+}
- //Cop-0 Regs. Bank 28:
- miscRegs[28].resize(8);
+double
+MipsISA::truncFP(double val)
+{
+ int trunc_val = (int) val;
+ return (double) trunc_val;
+}
- //Cop-0 Regs. Bank 29:
- miscRegs[29].resize(8);
+bool
+MipsISA::getFPConditionCode(uint32_t fcsr_reg, int cc)
+{
+ //uint32_t cc_bits = xc->readFloatReg(35);
+ return false;//regFile.floatRegfile.getConditionCode(cc);
+}
- //Cop-0 Regs. Bank 30:
- miscRegs[30].resize(1);
+uint32_t
+MipsISA::makeCCVector(uint32_t fcsr, int num, bool val)
+{
+ int shift = (num == 0) ? 22 : num + 23;
- //Cop-0 Regs. Bank 31:
- miscRegs[31].resize(1);*/
+ fcsr = fcsr | (val << shift);
+ return fcsr;
}
-
-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); }
@@ -327,12 +140,25 @@ TruncPage(Addr addr)
static inline Addr
RoundPage(Addr addr)
{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); }
+#endif
+
+void
+IntRegFile::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY(regs, NumIntRegs);
+}
+
+void
+IntRegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(regs, NumIntRegs);
+}
void
RegFile::serialize(std::ostream &os)
{
- SERIALIZE_ARRAY(intRegFile, NumIntRegs);
- SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ intRegFile.serialize(os);
+ //SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
//SERIALIZE_SCALAR(miscRegs.fpcr);
//SERIALIZE_SCALAR(miscRegs.uniq);
//SERIALIZE_SCALAR(miscRegs.lock_flag);
@@ -352,8 +178,8 @@ RegFile::serialize(std::ostream &os)
void
RegFile::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ARRAY(intRegFile, NumIntRegs);
- UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ intRegFile.unserialize(cp, section);
+ //UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
//UNSERIALIZE_SCALAR(miscRegs.fpcr);
//UNSERIALIZE_SCALAR(miscRegs.uniq);
//UNSERIALIZE_SCALAR(miscRegs.lock_flag);
diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh
index 1dfa0dc7a..148c405df 100644
--- a/arch/mips/isa_traits.hh
+++ b/arch/mips/isa_traits.hh
@@ -29,9 +29,14 @@
#ifndef __ARCH_MIPS_ISA_TRAITS_HH__
#define __ARCH_MIPS_ISA_TRAITS_HH__
-//#include "arch/mips/misc_regfile.hh"
+#include "arch/mips/constants.hh"
+#include "arch/mips/types.hh"
+#include "arch/mips/regfile/regfile.hh"
+#include "arch/mips/faults.hh"
+#include "arch/mips/utility.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
+#include "sim/byteswap.hh"
#include "sim/host.hh"
#include "sim/faults.hh"
@@ -40,9 +45,9 @@
class FastCPU;
class FullCPU;
class Checkpoint;
+class ExecContext;
namespace LittleEndianGuest {};
-using namespace LittleEndianGuest;
#define TARGET_MIPS
@@ -54,396 +59,107 @@ 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,
+#if !FULL_SYSTEM
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint32_t)v;
+ success = s;
+ }
- WatchHi0 = 145,//Bank 19: 145-152
- WatchHi1 = 146,
- WatchHi2 = 147,
- WatchHi3 = 148,
- WatchHi4 = 149,
- WatchHi5 = 150,
- WatchHi6 = 151,
- WatchHi7 = 152,
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint32_t)v;
+ }
- XCContext64 = 153,//Bank 20: 153-160
+ ~SyscallReturn() {}
- //Bank 21: 161-168
+ SyscallReturn& operator=(const SyscallReturn& s) {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
- //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,
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
- ErrorEPC = 249,//Bank 30: 241 - 248
+ private:
+ uint64_t retval;
+ bool success;
+};
+#endif
- DESAVE = 257,//Bank 31: 249-256
+namespace MipsISA
+{
+ using namespace LittleEndianGuest;
+
+ static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ if (return_value.successful()) {
+ // no error
+ regs->setIntReg(SyscallSuccessReg, 0);
+ regs->setIntReg(ReturnValueReg1, return_value.value());
+ } else {
+ // got an error, return details
+ regs->setIntReg(SyscallSuccessReg, (IntReg) -1);
+ regs->setIntReg(ReturnValueReg1, -return_value.value());
+ }
+ }
- //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;
+ StaticInstPtr decodeInst(ExtMachInst);
+ static inline ExtMachInst
+ makeExtMI(MachInst inst, const uint64_t &pc) {
#if FULL_SYSTEM
-
- typedef uint64_t InternalProcReg;
-
-#include "arch/mips/isa_fullsys_traits.hh"
-
+ ExtMachInst ext_inst = inst;
+ if (pc && 0x1)
+ return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
+ else
+ return ext_inst;
#else
- enum {
- NumInternalProcRegs = 0
- };
+ return ExtMachInst(inst);
#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);
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param xc The execution context.
+ */
+ template <class XC>
+ void zeroRegisters(XC *xc);
- // return a no-op instruction... used for instruction fetch faults
- extern const MachInst NoopMachInst;
+ const Addr MaxAddr = (Addr)-1;
- enum annotes {
- ANNOTE_NONE = 0,
- // An impossible number for instruction annotations
- ITOUCH_ANNOTE = 0xffffffff,
- };
+ void copyRegs(ExecContext *src, ExecContext *dest);
- void getMiscRegIdx(int reg_name,int &idx, int &sel);
+ uint64_t fpConvert(double fp_val, ConvertType cvt_type);
+ double roundFP(double val, int digits);
+ double truncFP(double val);
+ bool getFPConditionCode(uint32_t fcsr_reg, int cc);
+ uint32_t makeCCVector(uint32_t fcsr, int num, bool val);
+ // Machine operations
- static inline bool isCallerSaveIntegerRegister(unsigned int reg) {
- panic("register classification not implemented");
- return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
- }
+ void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
+ int regnum);
- static inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
- panic("register classification not implemented");
- return (reg >= 9 && reg <= 15);
- }
+ void restoreMachineReg(RegFile &regs, const AnyReg &reg,
+ int regnum);
- static inline bool isCallerSaveFloatRegister(unsigned int reg) {
- panic("register classification not implemented");
- return false;
- }
+#if 0
+ static void serializeSpecialRegs(const Serializable::Proxy &proxy,
+ const RegFile &regs);
- static inline bool isCalleeSaveFloatRegister(unsigned int reg) {
- panic("register classification not implemented");
- return false;
- }
+ static void unserializeSpecialRegs(const IniFile *db,
+ const std::string &category,
+ ConfigNode *node,
+ RegFile &regs);
+#endif
static inline Addr alignAddress(const Addr &addr,
unsigned int nbytes) {
@@ -470,77 +186,14 @@ extern const Addr PageOffset;
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
+using namespace MipsISA;
+
#endif // __ARCH_MIPS_ISA_TRAITS_HH__
diff --git a/arch/mips/linux/linux.cc b/arch/mips/linux/linux.cc
new file mode 100644
index 000000000..ebff886dd
--- /dev/null
+++ b/arch/mips/linux/linux.cc
@@ -0,0 +1,70 @@
+/*
+ * 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/linux/linux.hh"
+
+// open(2) flags translation table
+OpenFlagTransTable MipsLinux::openFlagTable[] = {
+#ifdef _MSC_VER
+ { MipsLinux::TGT_O_RDONLY, _O_RDONLY },
+ { MipsLinux::TGT_O_WRONLY, _O_WRONLY },
+ { MipsLinux::TGT_O_RDWR, _O_RDWR },
+ { MipsLinux::TGT_O_APPEND, _O_APPEND },
+ { MipsLinux::TGT_O_CREAT, _O_CREAT },
+ { MipsLinux::TGT_O_TRUNC, _O_TRUNC },
+ { MipsLinux::TGT_O_EXCL, _O_EXCL },
+#ifdef _O_NONBLOCK
+ { MipsLinux::TGT_O_NONBLOCK, _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+ { MipsLinux::TGT_O_NOCTTY, _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+ { MipsLinux::TGT_O_SYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+ { MipsLinux::TGT_O_RDONLY, O_RDONLY },
+ { MipsLinux::TGT_O_WRONLY, O_WRONLY },
+ { MipsLinux::TGT_O_RDWR, O_RDWR },
+ { MipsLinux::TGT_O_APPEND, O_APPEND },
+ { MipsLinux::TGT_O_CREAT, O_CREAT },
+ { MipsLinux::TGT_O_TRUNC, O_TRUNC },
+ { MipsLinux::TGT_O_EXCL, O_EXCL },
+ { MipsLinux::TGT_O_NONBLOCK, O_NONBLOCK },
+ { MipsLinux::TGT_O_NOCTTY, O_NOCTTY },
+#ifdef O_SYNC
+ { MipsLinux::TGT_O_SYNC, O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int MipsLinux::NUM_OPEN_FLAGS =
+ (sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
+
+
+
diff --git a/arch/mips/linux/linux.hh b/arch/mips/linux/linux.hh
new file mode 100644
index 000000000..fd08e8c87
--- /dev/null
+++ b/arch/mips/linux/linux.hh
@@ -0,0 +1,124 @@
+/*
+ * 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_MIPS_LINUX_HH
+#define __MIPS_MIPS_LINUX_HH
+
+#include "kern/linux/linux.hh"
+
+class MipsLinux : public Linux
+{
+ public:
+
+ /// 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;
+
+ //@{
+ /// open(2) flag values.
+ static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY
+ static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY
+ static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR
+ static const int TGT_O_NONBLOCK = 0x00000080; //!< O_NONBLOCK
+ static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND
+ static const int TGT_O_CREAT = 0x00000100; //!< O_CREAT
+ static const int TGT_O_TRUNC = 0x00000200; //!< O_TRUNC
+ static const int TGT_O_EXCL = 0x00000400; //!< O_EXCL
+ static const int TGT_O_NOCTTY = 0x00000800; //!< O_NOCTTY
+ static const int TGT_O_SYNC = 0x00000010; //!< O_SYNC
+ static const int TGT_O_DRD = 0x00010000; //!< O_DRD
+ static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO
+ static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE
+ static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC
+ static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC
+ //@}
+
+ /// For mmap().
+ static const unsigned TGT_MAP_ANONYMOUS = 0x800;
+
+ //@{
+ /// 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 getrusage().
+ static const int TGT_RUSAGE_SELF = 0;
+ static const int TGT_RUSAGE_CHILDREN = -1;
+ static const int TGT_RUSAGE_BOTH = -2;
+ //@}
+
+ //@{
+ /// For setsysinfo().
+ static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
+ //@}
+
+ //@{
+ /// ioctl() command codes.
+ static const unsigned TIOCGETP = 0x7408;
+ static const unsigned TIOCSETP = 0x7409;
+ static const unsigned TIOCSETN = 0x740a;
+ static const unsigned TIOCSETC = 0x7411;
+ static const unsigned TIOCGETC = 0x7412;
+ static const unsigned FIONREAD = 0x467f;
+ static const unsigned TIOCISATTY = 0x5480;
+ static const unsigned TIOCGETS = 0x7413;
+ static const unsigned TIOCGETA = 0x7417;
+ //@}
+
+ /// For table().
+ static const int TBL_SYSINFO = 12;
+
+ /// 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_NOFILE = 5,
+ TGT_RLIMIT_AS = 6,
+ TGT_RLIMIT_RSS = 7,
+ TGT_RLIMIT_VMEM = 7,
+ TGT_RLIMIT_NPROC = 8,
+ TGT_RLIMIT_MEMLOCK = 9,
+ TGT_RLIMIT_LOCKS = 10
+ };
+
+};
+
+#endif
diff --git a/arch/mips/linux/process.cc b/arch/mips/linux/process.cc
new file mode 100644
index 000000000..ffc5da2e1
--- /dev/null
+++ b/arch/mips/linux/process.cc
@@ -0,0 +1,429 @@
+/*
+ * 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/linux/linux.hh"
+#include "arch/mips/linux/process.hh"
+#include "arch/mips/isa_traits.hh"
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/linux.hh"
+
+#include "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace MipsISA;
+
+/// 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, "mips");
+
+ name.copyOut(xc->getMemPort());
+ return 0;
+}
+
+/// Target sys_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
+sys_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->getMemPort());
+ return 0;
+ }
+
+ default:
+ cerr << "sys_getsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
+
+ return 1;
+}
+
+/// Target sys_setsysinfo() handler.
+static SyscallReturn
+sys_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->getMemPort());
+ DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
+ " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
+ return 0;
+ }
+
+ default:
+ cerr << "sys_setsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
+
+ return 1;
+}
+
+
+SyscallDesc MipsLinuxProcess::syscallDescs[] = {
+ /* 0 */ SyscallDesc("syscall", unimplementedFunc),
+ /* 1 */ SyscallDesc("exit", exitFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", readFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("open", openFunc<MipsLinux>),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("waitpid", unimplementedFunc),
+ /* 8 */ SyscallDesc("creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("execve", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("time", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", chmodFunc<MipsLinux>),
+ /* 16 */ SyscallDesc("lchown", chownFunc),
+ /* 17 */ SyscallDesc("break", obreakFunc), /*obreak*/
+ /* 18 */ SyscallDesc("unused#18", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", lseekFunc),
+ /* 20 */ SyscallDesc("getpid", getpidFunc),
+ /* 21 */ SyscallDesc("mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("umount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", setuidFunc),
+ /* 24 */ SyscallDesc("getuid", getuidFunc),
+ /* 25 */ SyscallDesc("stime", unimplementedFunc),
+ /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("alarm", unimplementedFunc),
+ /* 28 */ SyscallDesc("unused#28", unimplementedFunc),
+ /* 29 */ SyscallDesc("pause", unimplementedFunc),
+ /* 30 */ SyscallDesc("utime", unimplementedFunc),
+ /* 31 */ SyscallDesc("stty", unimplementedFunc),
+ /* 32 */ SyscallDesc("gtty", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("nice", unimplementedFunc),
+ /* 35 */ SyscallDesc("ftime", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", ignoreFunc),
+ /* 38 */ SyscallDesc("rename", unimplementedFunc),
+ /* 39 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 40 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+ /* 43 */ SyscallDesc("times", unimplementedFunc),
+ /* 44 */ SyscallDesc("prof", unimplementedFunc),
+ /* 45 */ SyscallDesc("brk", obreakFunc),/*openFunc<MipsLinux>*/
+ /* 46 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 47 */ SyscallDesc("getgid", getgidFunc),
+ /* 48 */ SyscallDesc("signal", ignoreFunc),
+ /* 49 */ SyscallDesc("geteuid", geteuidFunc),
+ /* 50 */ SyscallDesc("getegid", getegidFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("umount2", unimplementedFunc),
+ /* 53 */ SyscallDesc("lock", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<MipsLinux>),
+ /* 55 */ SyscallDesc("fcntl", unimplementedFunc),
+ /* 56 */ SyscallDesc("mpx", unimplementedFunc),
+ /* 57 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 58 */ SyscallDesc("ulimit", unimplementedFunc),
+ /* 59 */ SyscallDesc("unused#59", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("ustat", unimplementedFunc),
+ /* 63 */ SyscallDesc("dup2", unimplementedFunc),
+ /* 64 */ SyscallDesc("getppid", getpagesizeFunc),
+ /* 65 */ SyscallDesc("getpgrp", unimplementedFunc),
+ /* 66 */ SyscallDesc("setsid", unimplementedFunc),
+ /* 67 */ SyscallDesc("sigaction",unimplementedFunc),
+ /* 68 */ SyscallDesc("sgetmask", unimplementedFunc),
+ /* 69 */ SyscallDesc("ssetmask", unimplementedFunc),
+ /* 70 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 71 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 73 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 74 */ SyscallDesc("sethostname", ignoreFunc),
+ /* 75 */ SyscallDesc("setrlimit", unimplementedFunc),
+ /* 76 */ SyscallDesc("getrlimit", unimplementedFunc),
+ /* 77 */ SyscallDesc("getrusage", unimplementedFunc),
+ /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
+ /* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 80 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 81 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 82 */ SyscallDesc("reserved#82", unimplementedFunc),
+ /* 83 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 84 */ SyscallDesc("unused#84", unimplementedFunc),
+ /* 85 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 86 */ SyscallDesc("uselib", unimplementedFunc),
+ /* 87 */ SyscallDesc("swapon", gethostnameFunc),
+ /* 88 */ SyscallDesc("reboot", unimplementedFunc),
+ /* 89 */ SyscallDesc("readdir", unimplementedFunc),
+ /* 90 */ SyscallDesc("mmap", mmapFunc<MipsLinux>),
+ /* 91 */ SyscallDesc("munmap",munmapFunc),
+ /* 92 */ SyscallDesc("truncate", fcntlFunc),
+ /* 93 */ SyscallDesc("ftruncate", unimplementedFunc),
+ /* 94 */ SyscallDesc("fchmod", unimplementedFunc),
+ /* 95 */ SyscallDesc("fchown", unimplementedFunc),
+ /* 96 */ SyscallDesc("getpriority", unimplementedFunc),
+ /* 97 */ SyscallDesc("setpriority", unimplementedFunc),
+ /* 98 */ SyscallDesc("profil", unimplementedFunc),
+ /* 99 */ SyscallDesc("statfs", unimplementedFunc),
+ /* 100 */ SyscallDesc("fstatfs", unimplementedFunc),
+ /* 101 */ SyscallDesc("ioperm", unimplementedFunc),
+ /* 102 */ SyscallDesc("socketcall", unimplementedFunc),
+ /* 103 */ SyscallDesc("syslog", unimplementedFunc),
+ /* 104 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 105 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 106 */ SyscallDesc("stat", statFunc<MipsLinux>),
+ /* 107 */ SyscallDesc("lstat", unimplementedFunc),
+ /* 108 */ SyscallDesc("fstat", fstatFunc<MipsLinux>),
+ /* 109 */ SyscallDesc("unused#109", unimplementedFunc),
+ /* 110 */ SyscallDesc("iopl", unimplementedFunc),
+ /* 111 */ SyscallDesc("vhangup", unimplementedFunc),
+ /* 112 */ SyscallDesc("idle", ignoreFunc),
+ /* 113 */ SyscallDesc("vm86", unimplementedFunc),
+ /* 114 */ SyscallDesc("wait4", unimplementedFunc),
+ /* 115 */ SyscallDesc("swapoff", unimplementedFunc),
+ /* 116 */ SyscallDesc("sysinfo", unimplementedFunc),
+ /* 117 */ SyscallDesc("ipc", unimplementedFunc),
+ /* 118 */ SyscallDesc("fsync", unimplementedFunc),
+ /* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
+ /* 120 */ SyscallDesc("clone", unimplementedFunc),
+ /* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
+ /* 122 */ SyscallDesc("uname", unameFunc),
+ /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
+ /* 124 */ SyscallDesc("adjtimex", unimplementedFunc),
+ /* 125 */ SyscallDesc("mprotect", ignoreFunc),
+ /* 126 */ SyscallDesc("sigprocmask", unimplementedFunc),
+ /* 127 */ SyscallDesc("create_module", unimplementedFunc),
+ /* 128 */ SyscallDesc("init_module", unimplementedFunc),
+ /* 129 */ SyscallDesc("delete_module", unimplementedFunc),
+ /* 130 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
+ /* 131 */ SyscallDesc("quotactl", unimplementedFunc),
+ /* 132 */ SyscallDesc("getpgid", unimplementedFunc),
+ /* 133 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 134 */ SyscallDesc("bdflush", unimplementedFunc),
+ /* 135 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 136 */ SyscallDesc("personality", unimplementedFunc),
+ /* 137 */ SyscallDesc("afs_syscall", unimplementedFunc),
+ /* 138 */ SyscallDesc("setfsuid", unimplementedFunc),
+ /* 139 */ SyscallDesc("setfsgid", unimplementedFunc),
+ /* 140 */ SyscallDesc("llseek", unimplementedFunc),
+ /* 141 */ SyscallDesc("getdents", unimplementedFunc),
+ /* 142 */ SyscallDesc("newselect", unimplementedFunc),
+ /* 143 */ SyscallDesc("flock", unimplementedFunc),
+ /* 144 */ SyscallDesc("msync", unimplementedFunc),/*getrlimitFunc<MipsLinux>*/
+ /* 145 */ SyscallDesc("readv", unimplementedFunc),
+ /* 146 */ SyscallDesc("writev", writevFunc<MipsLinux>),
+ /* 147 */ SyscallDesc("cacheflush", unimplementedFunc),
+ /* 148 */ SyscallDesc("cachectl", unimplementedFunc),
+ /* 149 */ SyscallDesc("sysmips", unimplementedFunc),
+ /* 150 */ SyscallDesc("unused#150", unimplementedFunc),
+ /* 151 */ SyscallDesc("getsid", unimplementedFunc),
+ /* 152 */ SyscallDesc("fdatasync", unimplementedFunc),
+ /* 153 */ SyscallDesc("sysctl", unimplementedFunc),
+ /* 154 */ SyscallDesc("mlock", unimplementedFunc),
+ /* 155 */ SyscallDesc("munlock", unimplementedFunc),
+ /* 156 */ SyscallDesc("mlockall", unimplementedFunc),
+ /* 157 */ SyscallDesc("munlockall", unimplementedFunc),
+ /* 158 */ SyscallDesc("sched_setparam", unimplementedFunc),
+ /* 159 */ SyscallDesc("sched_getparam", unimplementedFunc),
+ /* 160 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
+ /* 161 */ SyscallDesc("sched_getscheduler", unimplementedFunc),
+ /* 162 */ SyscallDesc("sched_yield", unimplementedFunc),
+ /* 163 */ SyscallDesc("sched_get_prioritymax", unimplementedFunc),
+ /* 164 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
+ /* 165 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
+ /* 166 */ SyscallDesc("nanosleep", unimplementedFunc),
+ /* 167 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 168 */ SyscallDesc("accept", unimplementedFunc),
+ /* 169 */ SyscallDesc("bind", unimplementedFunc),
+ /* 170 */ SyscallDesc("connect", unimplementedFunc),
+ /* 171 */ SyscallDesc("getpeername", unimplementedFunc),
+ /* 172 */ SyscallDesc("getsockname", unimplementedFunc),
+ /* 173 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 174 */ SyscallDesc("listen", unimplementedFunc),
+ /* 175 */ SyscallDesc("recv", unimplementedFunc),
+ /* 176 */ SyscallDesc("recvmsg", unimplementedFunc),
+ /* 177 */ SyscallDesc("send", unimplementedFunc),
+ /* 178 */ SyscallDesc("sendmsg", ignoreFunc),
+ /* 179 */ SyscallDesc("sendto", unimplementedFunc),
+ /* 180 */ SyscallDesc("setsockopt", unimplementedFunc),
+ /* 181 */ SyscallDesc("shutdown", unimplementedFunc),
+ /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+ /* 183 */ SyscallDesc("socket", ignoreFunc),
+ /* 184 */ SyscallDesc("socketpair", unimplementedFunc),
+ /* 185 */ SyscallDesc("setresuid", unimplementedFunc),
+ /* 186 */ SyscallDesc("getresuid", unimplementedFunc),
+ /* 187 */ SyscallDesc("query_module", unimplementedFunc),
+ /* 188 */ SyscallDesc("poll", unimplementedFunc),
+ /* 189 */ SyscallDesc("nfsservctl", unimplementedFunc),
+ /* 190 */ SyscallDesc("setresgid", unimplementedFunc),
+ /* 191 */ SyscallDesc("getresgid", unimplementedFunc),
+ /* 192 */ SyscallDesc("prctl", unimplementedFunc),
+ /* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
+ /* 194 */ SyscallDesc("rt_sigaction", ignoreFunc),
+ /* 195 */ SyscallDesc("rt_sigprocmask", ignoreFunc),
+ /* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc),
+ /* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
+ /* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
+ /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
+ /* 200 */ SyscallDesc("pread64", unimplementedFunc),
+ /* 201 */ SyscallDesc("pwrite64", unimplementedFunc),
+ /* 202 */ SyscallDesc("chown", unimplementedFunc),
+ /* 203 */ SyscallDesc("getcwd", unimplementedFunc),
+ /* 204 */ SyscallDesc("capget", unimplementedFunc),
+ /* 205 */ SyscallDesc("capset", unimplementedFunc),
+ /* 206 */ SyscallDesc("sigalstack", unimplementedFunc),
+ /* 207 */ SyscallDesc("sendfile", unimplementedFunc),
+ /* 208 */ SyscallDesc("getpmsg", unimplementedFunc),
+ /* 209 */ SyscallDesc("putpmsg", unimplementedFunc),
+ /* 210 */ SyscallDesc("mmap2", unimplementedFunc),
+ /* 211 */ SyscallDesc("truncate64", unimplementedFunc),
+ /* 212 */ SyscallDesc("ftruncate64", unimplementedFunc),
+ /* 213 */ SyscallDesc("stat64", unimplementedFunc),
+ /* 214 */ SyscallDesc("lstat64", lstat64Func<MipsLinux>),
+ /* 215 */ SyscallDesc("fstat64", fstat64Func<MipsLinux>),
+ /* 216 */ SyscallDesc("pivot_root", unimplementedFunc),
+ /* 217 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 218 */ SyscallDesc("madvise", unimplementedFunc),
+ /* 219 */ SyscallDesc("getdents64", unimplementedFunc),
+ /* 220 */ SyscallDesc("fcntl64", fcntlFunc),
+ /* 221 */ SyscallDesc("reserved#221", unimplementedFunc),
+ /* 222 */ SyscallDesc("gettid", unimplementedFunc),
+ /* 223 */ SyscallDesc("readahead", unimplementedFunc),
+ /* 224 */ SyscallDesc("setxattr", unimplementedFunc),
+ /* 225 */ SyscallDesc("lsetxattr", unimplementedFunc),
+ /* 226 */ SyscallDesc("fsetxattr", unimplementedFunc),
+ /* 227 */ SyscallDesc("getxattr", unimplementedFunc),
+ /* 228 */ SyscallDesc("lgetxattr", unimplementedFunc),
+ /* 229 */ SyscallDesc("fgetxattr", unimplementedFunc),
+ /* 230 */ SyscallDesc("listxattr", unimplementedFunc),
+ /* 231 */ SyscallDesc("llistxattr", unimplementedFunc),
+ /* 232 */ SyscallDesc("flistxattr", unimplementedFunc),
+ /* 233 */ SyscallDesc("removexattr", unimplementedFunc),
+ /* 234 */ SyscallDesc("lremovexattr", unimplementedFunc),
+ /* 235 */ SyscallDesc("fremovexattr", ignoreFunc),
+ /* 236 */ SyscallDesc("tkill", unimplementedFunc),
+ /* 237 */ SyscallDesc("sendfile64", unimplementedFunc),
+ /* 238 */ SyscallDesc("futex", unimplementedFunc),
+ /* 239 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
+ /* 240 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
+ /* 241 */ SyscallDesc("io_setup", unimplementedFunc),
+ /* 242 */ SyscallDesc("io_destroy", unimplementedFunc),
+ /* 243 */ SyscallDesc("io_getevents", unimplementedFunc),
+ /* 244 */ SyscallDesc("io_submit", unimplementedFunc),
+ /* 245 */ SyscallDesc("io_cancel", unimplementedFunc),
+ /* 246 */ SyscallDesc("exit_group", exitFunc),
+ /* 247 */ SyscallDesc("lookup_dcookie", unimplementedFunc),
+ /* 248 */ SyscallDesc("epoll_create", unimplementedFunc),
+ /* 249 */ SyscallDesc("epoll_ctl", unimplementedFunc),
+ /* 250 */ SyscallDesc("epoll_wait", unimplementedFunc),
+ /* 251 */ SyscallDesc("remap_file_pages", unimplementedFunc),
+ /* 252 */ SyscallDesc("set_tid_address", unimplementedFunc),
+ /* 253 */ SyscallDesc("restart_syscall", unimplementedFunc),
+ /* 254 */ SyscallDesc("fadvise64", unimplementedFunc),
+ /* 255 */ SyscallDesc("statfs64", unimplementedFunc),
+ /* 256 */ SyscallDesc("fstafs64", unimplementedFunc),
+ /* 257 */ SyscallDesc("timer_create", sys_getsysinfoFunc),
+ /* 258 */ SyscallDesc("timer_settime", sys_setsysinfoFunc),
+ /* 259 */ SyscallDesc("timer_gettime", unimplementedFunc),
+ /* 260 */ SyscallDesc("timer_getoverrun", unimplementedFunc),
+ /* 261 */ SyscallDesc("timer_delete", unimplementedFunc),
+ /* 262 */ SyscallDesc("clock_settime", unimplementedFunc),
+ /* 263 */ SyscallDesc("clock_gettime", unimplementedFunc),
+ /* 264 */ SyscallDesc("clock_getres", unimplementedFunc),
+ /* 265 */ SyscallDesc("clock_nanosleep", unimplementedFunc),
+ /* 266 */ SyscallDesc("tgkill", unimplementedFunc),
+ /* 267 */ SyscallDesc("utimes", unimplementedFunc),
+ /* 268 */ SyscallDesc("mbind", unimplementedFunc),
+ /* 269 */ SyscallDesc("get_mempolicy", unimplementedFunc),
+ /* 270 */ SyscallDesc("set_mempolicy", unimplementedFunc),
+ /* 271 */ SyscallDesc("mq_open", unimplementedFunc),
+ /* 272 */ SyscallDesc("mq_unlink", unimplementedFunc),
+ /* 273 */ SyscallDesc("mq_timedsend", unimplementedFunc),
+ /* 274 */ SyscallDesc("mq_timedreceive", unimplementedFunc),
+ /* 275 */ SyscallDesc("mq_notify", unimplementedFunc),
+ /* 276 */ SyscallDesc("mq_getsetattr", unimplementedFunc),
+ /* 277 */ SyscallDesc("vserver", unimplementedFunc),
+ /* 278 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 279 */ SyscallDesc("unknown #279", unimplementedFunc),
+ /* 280 */ SyscallDesc("add_key", unimplementedFunc),
+ /* 281 */ SyscallDesc("request_key", unimplementedFunc),
+ /* 282 */ SyscallDesc("keyctl", unimplementedFunc),
+};
+
+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)
+ : MipsLiveProcess(name, objFile, system, 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)
+{
+ //MIPS32 syscalls are in the range of 4000 - 4999
+ int m5_sys_idx = callnum - 4000;
+
+ if (m5_sys_idx < 0 || m5_sys_idx > Num_Syscall_Descs)
+ return NULL;
+
+ return &syscallDescs[m5_sys_idx];
+}
diff --git a/arch/mips/linux_process.hh b/arch/mips/linux/process.hh
index 5408a6c44..68da3227b 100644
--- a/arch/mips/linux_process.hh
+++ b/arch/mips/linux/process.hh
@@ -29,16 +29,17 @@
#ifndef __MIPS_LINUX_PROCESS_HH__
#define __MIPS_LINUX_PROCESS_HH__
-#include "sim/process.hh"
+#include "arch/mips/process.hh"
/// A process with emulated Mips/Linux syscalls.
-class MipsLinuxProcess : public LiveProcess
+class MipsLinuxProcess : public MipsLiveProcess
{
public:
/// Constructor.
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);
diff --git a/arch/mips/linux_process.cc b/arch/mips/linux_process.cc
deleted file mode 100644
index 1d4f62350..000000000
--- a/arch/mips/linux_process.cc
+++ /dev/null
@@ -1,588 +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 "arch/mips/common_syscall_emul.hh"
-#include "arch/mips/linux_process.hh"
-#include "arch/mips/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 MipsISA;
-
-/// 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, "mips");
-
- name.copyOut(xc->mem);
- return 0;
-}
-
-/// Target osf_getsysyinfo() handler. Even though this call is
-/// borrowed from Tru64, the subcases that get used appear to be
-/// different in practice from those used by Tru64 processes.
-static SyscallReturn
-osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 45: { // GSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- *fpcr = 0;
- fpcr.copyOut(xc->mem);
- return 0;
- }
-
- default:
- cerr << "osf_getsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
-}
-
-/// Target osf_setsysinfo() handler.
-static SyscallReturn
-osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 14: { // SSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- fpcr.copyIn(xc->mem);
- DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
- " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
- return 0;
- }
-
- default:
- cerr << "osf_setsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
-}
-
-
-SyscallDesc MipsLinuxProcess::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", getpidFunc),
- /* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
- /* 22 */ SyscallDesc("umount", unimplementedFunc),
- /* 23 */ SyscallDesc("setuid", setuidFunc),
- /* 24 */ SyscallDesc("getxuid", getuidFunc),
- /* 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", unimplementedFunc),
- /* 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", getgidFunc),
- /* 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)
-};
-
-MipsLinuxProcess::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)
- : 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/process.cc b/arch/mips/process.cc
index 6de44fe9f..7831551be 100644
--- a/arch/mips/process.cc
+++ b/arch/mips/process.cc
@@ -26,22 +26,37 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/mips/isa_traits.hh"
#include "arch/mips/process.hh"
+#include "arch/mips/linux/process.hh"
+#include "base/loader/object_file.hh"
+#include "base/misc.hh"
+#include "cpu/exec_context.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace MipsISA;
-namespace MipsISA
-{
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
+MipsLiveProcess *
+MipsLiveProcess::create(const std::string &nm, System *system, int stdin_fd,
+ int stdout_fd, int stderr_fd, std::string executable,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
{
- LiveProcess * process = NULL;
- if (objFile->getArch() != ObjectFile::MIPS)
+ MipsLiveProcess *process = NULL;
+
+ ObjectFile *objFile = createObjectFile(executable);
+ if (objFile == NULL) {
+ fatal("Can't load object file %s", executable);
+ }
+
+
+ if (objFile->getArch() != ObjectFile::Mips)
fatal("Object file does not match architecture.");
switch (objFile->getOpSys()) {
case ObjectFile::Linux:
- process = new MipsLinuxProcess(nm, objFile,
+ process = new MipsLinuxProcess(nm, objFile, system,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
break;
@@ -49,8 +64,98 @@ createProcess(const string &nm, ObjectFile * objFile,
default:
fatal("Unknown/unsupported operating system.");
}
+
+ if (process == NULL)
+ fatal("Unknown error creating process object.");
return process;
}
-} // namespace MipsISA
+MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
+ : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
+ argv, envp)
+{
+
+ // XXX all the below need to be updated for SPARC - Ali
+ brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
+ brk_point = roundUp(brk_point, VMPageSize);
+
+ // Set up stack. On Alpha, stack goes below text section. This
+ // code should get moved to some architecture-specific spot.
+ stack_base = objFile->textBase() - (409600+4096);
+
+ // Set up region for mmaps. Tru64 seems to start just above 0 and
+ // grow up from there.
+ mmap_start = mmap_end = 0x10000;
+
+ // Set pointer for next thread stack. Reserve 8M for main stack.
+ next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+
+}
+
+void
+MipsLiveProcess::startup()
+{
+ argsInit(MachineBytes, VMPageSize);
+}
+
+
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(MipsLiveProcess)
+
+ VectorParam<string> cmd;
+ Param<string> executable;
+ Param<string> input;
+ Param<string> output;
+ VectorParam<string> env;
+ SimObjectParam<System *> system;
+
+END_DECLARE_SIM_OBJECT_PARAMS(MipsLiveProcess)
+
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(MipsLiveProcess)
+
+ INIT_PARAM(cmd, "command line (executable plus arguments)"),
+ INIT_PARAM(executable, "executable (overrides cmd[0] if set)"),
+ INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
+ INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
+ INIT_PARAM(env, "environment settings"),
+ INIT_PARAM(system, "system")
+
+END_INIT_SIM_OBJECT_PARAMS(MipsLiveProcess)
+
+
+CREATE_SIM_OBJECT(MipsLiveProcess)
+{
+ string in = input;
+ string out = output;
+
+ // initialize file descriptors to default: same as simulator
+ int stdin_fd, stdout_fd, stderr_fd;
+
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else
+ stdin_fd = Process::openInputFile(input);
+
+ if (out == "stdout" || out == "cout")
+ stdout_fd = STDOUT_FILENO;
+ else if (out == "stderr" || out == "cerr")
+ stdout_fd = STDERR_FILENO;
+ else
+ stdout_fd = Process::openOutputFile(out);
+
+ stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+
+ return MipsLiveProcess::create(getInstanceName(), system,
+ stdin_fd, stdout_fd, stderr_fd,
+ (string)executable == "" ? cmd[0] : executable,
+ cmd, env);
+}
+
+
+REGISTER_SIM_OBJECT("MipsLiveProcess", MipsLiveProcess)
+
diff --git a/arch/mips/process.hh b/arch/mips/process.hh
index ab4323107..2a13dc955 100644
--- a/arch/mips/process.hh
+++ b/arch/mips/process.hh
@@ -29,17 +29,36 @@
#ifndef __MIPS_PROCESS_HH__
#define __MIPS_PROCESS_HH__
-#include "arch/mips/linux_process.hh"
-#include "base/loader/object_file.hh"
+#include <string>
+#include <vector>
+#include "sim/process.hh"
-namespace MipsISA
+class LiveProcess;
+class ObjectFile;
+class System;
+
+class MipsLiveProcess : public LiveProcess
{
+ protected:
+ MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
+
+ void startup();
+
+ public:
+ // this function is used to create the LiveProcess object, since
+ // we can't tell which subclass of LiveProcess to use until we
+ // open and look at the object file.
+ static MipsLiveProcess *create(const std::string &nm,
+ System *_system,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::string executable,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
-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/regfile/float_regfile.hh b/arch/mips/regfile/float_regfile.hh
new file mode 100644
index 000000000..15c6f97f4
--- /dev/null
+++ b/arch/mips/regfile/float_regfile.hh
@@ -0,0 +1,159 @@
+/*
+ * 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_FLOAT_REGFILE_HH__
+#define __ARCH_MIPS_FLOAT_REGFILE_HH__
+
+#include "arch/mips/types.hh"
+#include "arch/mips/constants.hh"
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "sim/byteswap.hh"
+#include "sim/faults.hh"
+#include "sim/host.hh"
+
+class Checkpoint;
+class ExecContext;
+class Regfile;
+
+namespace MipsISA
+{
+ class FloatRegFile
+ {
+ protected:
+ FloatReg32 regs[NumFloatRegs];
+
+ public:
+
+ void clear()
+ {
+ bzero(regs, sizeof(regs));
+ }
+
+ double readReg(int floatReg, int width)
+ {
+ switch(width)
+ {
+ case SingleWidth:
+ void *float_ptr = &regs[floatReg];
+ return *(float *) float_ptr;
+
+ case DoubleWidth:
+ uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg];
+ void *double_ptr = &double_val;
+ return *(double *) double_ptr;
+
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ }
+
+ FloatRegBits readRegBits(int floatReg, int width)
+ {
+ if (floatReg < NumFloatArchRegs - 1) {
+ switch(width)
+ {
+ case SingleWidth:
+ return regs[floatReg];
+
+ case DoubleWidth:
+ return (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg];
+
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ } else {
+ if (width > SingleWidth)
+ assert("Control Regs are only 32 bits wide");
+
+ return regs[floatReg];
+ }
+ }
+
+ Fault setReg(int floatReg, const FloatReg &val, int width)
+ {
+
+ switch(width)
+ {
+ case SingleWidth:
+ float temp = val;
+ void *float_ptr = &temp;
+ regs[floatReg] = *(FloatReg32 *) float_ptr;
+ break;
+
+ case DoubleWidth:
+ const void *double_ptr = &val;
+ FloatReg64 temp_double = *(FloatReg64 *) double_ptr;
+ regs[floatReg + 1] = temp_double >> 32;
+ regs[floatReg] = temp_double;
+ break;
+
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+
+ return NoFault;
+ }
+
+ Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
+ {
+ using namespace std;
+
+ switch(width)
+ {
+ case SingleWidth:
+ regs[floatReg] = val;
+ break;
+
+ case DoubleWidth:
+ regs[floatReg + 1] = val >> 32;
+ regs[floatReg] = val;
+ break;
+
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ return NoFault;
+ }
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ enum MiscFloatRegNums {
+ FIR = NumFloatArchRegs,
+ FCCR,
+ FEXR,
+ FENR,
+ FCSR
+ };
+
+} // namespace MipsISA
+
+#endif
diff --git a/arch/mips/regfile/int_regfile.hh b/arch/mips/regfile/int_regfile.hh
new file mode 100644
index 000000000..3cd87734d
--- /dev/null
+++ b/arch/mips/regfile/int_regfile.hh
@@ -0,0 +1,73 @@
+/*
+ * 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_INT_REGFILE_HH__
+#define __ARCH_MIPS_INT_REGFILE_HH__
+
+#include "arch/mips/types.hh"
+#include "arch/mips/constants.hh"
+#include "base/misc.hh"
+#include "sim/faults.hh"
+
+class Checkpoint;
+class ExecContext;
+class Regfile;
+
+namespace MipsISA
+{
+ class IntRegFile
+ {
+ protected:
+ IntReg regs[NumIntRegs];
+
+ public:
+ IntReg readReg(int intReg)
+ {
+ return regs[intReg];
+ }
+
+ Fault setReg(int intReg, const IntReg &val)
+ {
+ regs[intReg] = val;
+ return NoFault;
+ }
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ };
+
+ enum MiscIntRegNums {
+ HI = NumIntArchRegs,
+ LO
+ };
+
+} // namespace MipsISA
+
+#endif
diff --git a/arch/mips/regfile/misc_regfile.hh b/arch/mips/regfile/misc_regfile.hh
new file mode 100644
index 000000000..9f054e5f7
--- /dev/null
+++ b/arch/mips/regfile/misc_regfile.hh
@@ -0,0 +1,96 @@
+/*
+ * 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_MISC_REGFILE_HH__
+#define __ARCH_MIPS_MISC_REGFILE_HH__
+
+#include "arch/mips/types.hh"
+#include "arch/mips/constants.hh"
+#include "sim/faults.hh"
+
+class Checkpoint;
+class ExecContext;
+class Regfile;
+
+namespace MipsISA
+{
+ 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
+
+ MiscReg miscRegFile[NumMiscRegs];
+
+ public:
+ //These functions should be removed once the simplescalar cpu model
+ //has been replaced.
+ int getInstAsid();
+ int getDataAsid();
+
+ void copyMiscRegs(ExecContext *xc);
+
+ 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;
+ };
+} // namespace MipsISA
+
+#endif
diff --git a/arch/mips/regfile/regfile.hh b/arch/mips/regfile/regfile.hh
new file mode 100644
index 000000000..e77571b33
--- /dev/null
+++ b/arch/mips/regfile/regfile.hh
@@ -0,0 +1,199 @@
+/*
+ * 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_REGFILE_HH__
+#define __ARCH_MIPS_REGFILE_HH__
+
+#include "arch/mips/types.hh"
+#include "arch/mips/constants.hh"
+#include "arch/mips/regfile/int_regfile.hh"
+#include "arch/mips/regfile/float_regfile.hh"
+#include "arch/mips/regfile/misc_regfile.hh"
+#include "sim/faults.hh"
+
+class Checkpoint;
+class ExecContext;
+
+namespace MipsISA
+{
+ class RegFile {
+ protected:
+ IntRegFile intRegFile; // (signed) integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegFile; // control register file
+
+ public:
+
+ void clear()
+ {
+ bzero(&intRegFile, sizeof(intRegFile));
+ bzero(&floatRegFile, sizeof(floatRegFile));
+ bzero(&miscRegFile, sizeof(miscRegFile));
+ }
+
+ MiscReg readMiscReg(int miscReg)
+ {
+ return miscRegFile.readReg(miscReg);
+ }
+
+ MiscReg readMiscRegWithEffect(int miscReg,
+ Fault &fault, ExecContext *xc)
+ {
+ fault = NoFault;
+ return miscRegFile.readRegWithEffect(miscReg, fault, xc);
+ }
+
+ Fault setMiscReg(int miscReg, const MiscReg &val)
+ {
+ return miscRegFile.setReg(miscReg, val);
+ }
+
+ Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
+ ExecContext * xc)
+ {
+ return miscRegFile.setRegWithEffect(miscReg, val, xc);
+ }
+
+ FloatReg readFloatReg(int floatReg)
+ {
+ return floatRegFile.readReg(floatReg,SingleWidth);
+ }
+
+ FloatReg readFloatReg(int floatReg, int width)
+ {
+ return floatRegFile.readReg(floatReg,width);
+ }
+
+ FloatRegBits readFloatRegBits(int floatReg)
+ {
+ return floatRegFile.readRegBits(floatReg,SingleWidth);
+ }
+
+ FloatRegBits readFloatRegBits(int floatReg, int width)
+ {
+ return floatRegFile.readRegBits(floatReg,width);
+ }
+
+ Fault setFloatReg(int floatReg, const FloatReg &val)
+ {
+ return floatRegFile.setReg(floatReg, val, SingleWidth);
+ }
+
+ Fault setFloatReg(int floatReg, const FloatReg &val, int width)
+ {
+ return floatRegFile.setReg(floatReg, val, width);
+ }
+
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
+ {
+ return floatRegFile.setRegBits(floatReg, val, SingleWidth);
+ }
+
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
+ {
+ return floatRegFile.setRegBits(floatReg, val, width);
+ }
+
+ IntReg readIntReg(int intReg)
+ {
+ return intRegFile.readReg(intReg);
+ }
+
+ Fault setIntReg(int intReg, const IntReg &val)
+ {
+ return intRegFile.setReg(intReg, val);
+ }
+ protected:
+
+ 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
+ public:
+ Addr readPC()
+ {
+ return pc;
+ }
+
+ void setPC(Addr val)
+ {
+ pc = val;
+ }
+
+ Addr readNextPC()
+ {
+ return npc;
+ }
+
+ void setNextPC(Addr val)
+ {
+ npc = val;
+ }
+
+ Addr readNextNPC()
+ {
+ return nnpc;
+ }
+
+ void setNextNPC(Addr val)
+ {
+ nnpc = val;
+ }
+
+
+#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 serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ typedef int ContextParam;
+ typedef int ContextVal;
+
+ void changeContext(ContextParam param, ContextVal val)
+ {
+ }
+ };
+
+ void copyRegs(ExecContext *src, ExecContext *dest);
+
+ void copyMiscRegs(ExecContext *src, ExecContext *dest);
+
+#if FULL_SYSTEM
+ void copyIprs(ExecContext *src, ExecContext *dest);
+#endif
+} // namespace MipsISA
+
+#endif
diff --git a/arch/mips/types.hh b/arch/mips/types.hh
new file mode 100644
index 000000000..4d5fb3456
--- /dev/null
+++ b/arch/mips/types.hh
@@ -0,0 +1,92 @@
+/*
+ * 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_TYPES_HH__
+#define __ARCH_MIPS_TYPES_HH__
+
+#include "sim/host.hh"
+
+namespace MipsISA
+{
+ typedef uint32_t MachInst;
+ typedef uint64_t ExtMachInst;
+ typedef uint8_t RegIndex;
+
+ typedef uint32_t IntReg;
+
+ // floating point register file entry type
+ typedef double FloatReg;
+ typedef uint32_t FloatReg32;
+ typedef uint64_t FloatReg64;
+ typedef uint64_t FloatRegBits;
+
+ // cop-0/cop-1 system control register
+ typedef uint64_t MiscReg;
+ typedef uint64_t InternalProcReg;
+
+ typedef union {
+ IntReg intreg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ //used in FP convert & round function
+ enum ConvertType{
+ SINGLE_TO_DOUBLE,
+ SINGLE_TO_WORD,
+ SINGLE_TO_LONG,
+
+ DOUBLE_TO_SINGLE,
+ DOUBLE_TO_WORD,
+ DOUBLE_TO_LONG,
+
+ LONG_TO_SINGLE,
+ LONG_TO_DOUBLE,
+ LONG_TO_WORD,
+ LONG_TO_PS,
+
+ WORD_TO_SINGLE,
+ WORD_TO_DOUBLE,
+ WORD_TO_LONG,
+ WORD_TO_PS,
+
+ PL_TO_SINGLE,
+ PU_TO_SINGLE
+ };
+
+ //used in FP convert & round function
+ enum RoundMode{
+ RND_ZERO,
+ RND_DOWN,
+ RND_UP,
+ RND_NEAREST
+ };
+
+} // namespace MipsISA
+
+#endif
diff --git a/arch/mips/utility.hh b/arch/mips/utility.hh
new file mode 100644
index 000000000..b213a9f24
--- /dev/null
+++ b/arch/mips/utility.hh
@@ -0,0 +1,41 @@
+/*
+ * 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_UTILITY_HH__
+#define __ARCH_MIPS_UTILITY_HH__
+
+#include "arch/mips/types.hh"
+#include "arch/mips/constants.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+namespace MipsISA {
+
+};
+
+#endif
diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript
index edff5821e..fd0df9349 100644
--- a/arch/sparc/SConscript
+++ b/arch/sparc/SConscript
@@ -57,8 +57,8 @@ full_system_sources = Split('''
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
- common_syscall_emul.cc
- linux_process.cc
+ linux/linux.cc
+ linux/process.cc
process.cc
''')
diff --git a/arch/sparc/faults.cc b/arch/sparc/faults.cc
index b48fc600b..e83bba800 100644
--- a/arch/sparc/faults.cc
+++ b/arch/sparc/faults.cc
@@ -89,10 +89,10 @@ 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 PrivilegedOpcode::_name = "priv_opcode";
+TrapType PrivilegedOpcode::_trapType = 0x011;
+FaultPriority PrivilegedOpcode::_priority = 6;
+FaultStat PrivilegedOpcode::_count;
FaultName UnimplementedLDD::_name = "unimp_ldd";
TrapType UnimplementedLDD::_trapType = 0x012;
@@ -159,10 +159,10 @@ 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 PrivilegedAction::_name = "priv_action";
+TrapType PrivilegedAction::_trapType = 0x037;
+FaultPriority PrivilegedAction::_priority = 11;
+FaultStat PrivilegedAction::_count;
FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
@@ -179,13 +179,13 @@ TrapType AsyncDataError::_trapType = 0x040;
FaultPriority AsyncDataError::_priority = 2;
FaultStat AsyncDataError::_count;
-//The enumerated faults
-
FaultName CleanWindow::_name = "clean_win";
-TrapType CleanWindow::_baseTrapType = 0x024;
+TrapType CleanWindow::_trapType = 0x024;
FaultPriority CleanWindow::_priority = 10;
FaultStat CleanWindow::_count;
+//The enumerated faults
+
FaultName InterruptLevelN::_name = "interrupt_n";
TrapType InterruptLevelN::_baseTrapType = 0x041;
FaultStat InterruptLevelN::_count;
@@ -215,7 +215,10 @@ TrapType TrapInstruction::_baseTrapType = 0x100;
FaultPriority TrapInstruction::_priority = 16;
FaultStat TrapInstruction::_count;
-
+FaultName UnimpFault::_name = "Unimplemented Simulator feature";
+TrapType UnimpFault::_trapType = 0x000;
+FaultPriority UnimpFault::_priority = 0;
+FaultStat UnimpFault::_count;
#if FULL_SYSTEM
@@ -242,6 +245,12 @@ void SparcFault::invoke(ExecContext * xc)
xc->regs.npc = xc->regs.pc + sizeof(MachInst);*/
}
+void UnimpFault::invoke(ExecContext * xc)
+{
+ panic("Unimpfault: %s\n", panicStr.c_str());
+}
+
+
#endif
} // namespace SparcISA
diff --git a/arch/sparc/faults.hh b/arch/sparc/faults.hh
index 318b1ad5a..87de8daaa 100644
--- a/arch/sparc/faults.hh
+++ b/arch/sparc/faults.hh
@@ -216,7 +216,7 @@ class IllegalInstruction : public SparcFault
FaultStat & countStat() {return _count;}
};
-class PrivelegedOpcode : public SparcFault
+class PrivilegedOpcode : public SparcFault
{
private:
static FaultName _name;
@@ -412,7 +412,7 @@ class STDFMemAddressNotAligned : public SparcFault
FaultStat & countStat() {return _count;}
};
-class PrivelegedAction : public SparcFault
+class PrivilegedAction : public SparcFault
{
private:
static FaultName _name;
@@ -468,31 +468,30 @@ class AsyncDataError : public SparcFault
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
+class CleanWindow : public SparcFault
{
private:
static FaultName _name;
- static TrapType _baseTrapType;
+ static TrapType _trapType;
static FaultPriority _priority;
static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
public:
- CleanWindow(uint32_t n) : EnumeratedFault(n) {;}
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 InterruptLevelN : public EnumeratedFault
{
private:
@@ -582,6 +581,29 @@ class TrapInstruction : public EnumeratedFault
FaultStat & countStat() {return _count;}
};
+class UnimpFault : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ std::string panicStr;
+ public:
+ UnimpFault(std::string _str)
+ : panicStr(_str)
+ { }
+
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+
} // SparcISA namespace
#endif // __FAULTS_HH__
diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa
index 992504369..cb370a3e7 100644
--- a/arch/sparc/isa/base.isa
+++ b/arch/sparc/isa/base.isa
@@ -5,15 +5,19 @@
output header {{
- struct condCodes
+ union CondCodes
{
- uint8_t c:1;
- uint8_t v:1;
- uint8_t z:1;
- uint8_t n:1;
- }
+ struct
+ {
+ uint8_t c:1;
+ uint8_t v:1;
+ uint8_t z:1;
+ uint8_t n:1;
+ };
+ uint32_t bits;
+ };
- enum condTest
+ enum CondTest
{
Always=0x8,
Never=0x0,
@@ -31,7 +35,9 @@ output header {{
Negative=0x6,
OverflowClear=0xF,
OverflowSet=0x7
- }
+ };
+
+ extern char * CondTestAbbrev[];
/**
* Base class for all SPARC static instructions.
@@ -48,19 +54,100 @@ output header {{
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
+
+ void printReg(std::ostream &os, int reg) const;
};
- bool passesCondition(condCodes codes, condTest condition);
+ bool passesCondition(uint32_t codes, uint32_t condition);
+
+ inline int64_t sign_ext(uint64_t data, int origWidth)
+ {
+ int shiftAmount = 64 - origWidth;
+ return (((int64_t)data) << shiftAmount) >> shiftAmount;
+ }
}};
output decoder {{
+ char * CondTestAbbrev[] =
+ {
+ "nev", //Never
+ "e", //Equal
+ "le", //Less or Equal
+ "l", //Less
+ "leu", //Less or Equal Unsigned
+ "c", //Carry set
+ "n", //Negative
+ "o", //Overflow set
+ "a", //Always
+ "ne", //Not Equal
+ "g", //Greater
+ "ge", //Greater or Equal
+ "gu", //Greater Unsigned
+ "cc", //Carry clear
+ "p", //Positive
+ "oc" //Overflow Clear
+ };
+}};
+
+def template ROrImmDecode {{
+ {
+ return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
+ : (SparcStaticInst *)(new %(class_name)s(machInst)));
+ }
+}};
+
+let {{
+ def splitOutImm(code):
+ matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)')
+ rOrImmMatch = matcher.search(code)
+ if (rOrImmMatch == None):
+ return (False, code, '', '', '')
+ rString = rOrImmMatch.group("rNum")
+ iString = rOrImmMatch.group("iNum")
+ orig_code = code
+ code = matcher.sub('Rs' + rOrImmMatch.group("rNum"), orig_code)
+ imm_code = matcher.sub('imm', orig_code)
+ return (True, code, imm_code, rString, iString)
+}};
+
+output decoder {{
+
+ inline void printMnemonic(std::ostream &os, const char * mnemonic)
+ {
+ ccprintf(os, "\t%s ", mnemonic);
+ }
+
+ void
+ SparcStaticInst::printReg(std::ostream &os, int reg) const
+ {
+ const int MaxGlobal = 8;
+ const int MaxOutput = 16;
+ const int MaxLocal = 24;
+ const int MaxInput = 32;
+ if (reg == FramePointerReg)
+ ccprintf(os, "%%fp");
+ else if (reg == StackPointerReg)
+ ccprintf(os, "%%sp");
+ else if(reg < MaxGlobal)
+ ccprintf(os, "%%g%d", reg);
+ else if(reg < MaxOutput)
+ ccprintf(os, "%%o%d", reg - MaxGlobal);
+ else if(reg < MaxLocal)
+ ccprintf(os, "%%l%d", reg - MaxOutput);
+ else if(reg < MaxInput)
+ ccprintf(os, "%%i%d", reg - MaxLocal);
+ else {
+ ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
+ }
+ }
+
std::string SparcStaticInst::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
- ccprintf(ss, "%-10s ", mnemonic);
+ printMnemonic(ss, mnemonic);
// just print the first two source regs... if there's
// a third one, it's a read-modify-write dest (Rc),
@@ -87,8 +174,10 @@ output decoder {{
return ss.str();
}
- bool passesCondition(condCodes codes, condTest condition)
+ bool passesCondition(uint32_t codes, uint32_t condition)
{
+ CondCodes condCodes;
+ condCodes.bits = codes;
switch(condition)
{
case Always:
@@ -96,34 +185,36 @@ output decoder {{
case Never:
return false;
case NotEqual:
- return !codes.z;
+ return !condCodes.z;
case Equal:
- return codes.z;
+ return condCodes.z;
case Greater:
- return !(codes.z | (codes.n ^ codes.v));
+ return !(condCodes.z | (condCodes.n ^ condCodes.v));
case LessOrEqual:
- return codes.z | (codes.n ^ codes.v);
+ return condCodes.z | (condCodes.n ^ condCodes.v);
case GreaterOrEqual:
- return !(codes.n ^ codes.v);
+ return !(condCodes.n ^ condCodes.v);
case Less:
- return (codes.n ^ codes.v);
+ return (condCodes.n ^ condCodes.v);
case GreaterUnsigned:
- return !(codes.c | codes.z);
+ return !(condCodes.c | condCodes.z);
case LessOrEqualUnsigned:
- return (codes.c | codes.z);
+ return (condCodes.c | condCodes.z);
case CarryClear:
- return !codes.c;
+ return !condCodes.c;
case CarrySet:
- return codes.c;
+ return condCodes.c;
case Positive:
- return !codes.n;
+ return !condCodes.n;
case Negative:
- return codes.n;
+ return condCodes.n;
case OverflowClear:
- return !codes.v;
+ return !condCodes.v;
case OverflowSet:
- return codes.v;
+ return condCodes.v;
}
+ panic("Tried testing condition nonexistant "
+ "condition code %d", condition);
}
}};
diff --git a/arch/sparc/isa/bitfields.isa b/arch/sparc/isa/bitfields.isa
index b0ac57575..2e4478099 100644
--- a/arch/sparc/isa/bitfields.isa
+++ b/arch/sparc/isa/bitfields.isa
@@ -7,13 +7,11 @@
// 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 BPCC <21:20>; // for BPcc & FBPcc
+def bitfield FCMPCC <26:56>; // for FCMP & FCMPEa
+def bitfield FMOVCC <13:11>; // for FMOVcc
+def bitfield CC <12:11>; // for MOVcc & Tcc
+def bitfield MOVCC3 <18>; // also for MOVcc
def bitfield CMASK <6:4>;
def bitfield COND2 <28:25>;
def bitfield COND4 <17:14>;
@@ -46,5 +44,5 @@ 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 SW_TRAP <7:0>;
def bitfield X <12>;
diff --git a/arch/sparc/isa/decoder.isa b/arch/sparc/isa/decoder.isa
index eb458211b..b9e83afd6 100644
--- a/arch/sparc/isa/decoder.isa
+++ b/arch/sparc/isa/decoder.isa
@@ -3,660 +3,693 @@
// 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)
+decode OP default Unknown::unknown()
+{
+ 0x0: decode OP2
+ {
+ //Throw an illegal instruction acception
+ 0x0: Trap::illtrap({{fault = new IllegalInstruction;}});
+ 0x1: decode BPCC
+ {
+ format Branch19
+ {
+ 0x0: bpcci({{
+ if(passesCondition(CcrIcc, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x2: bpccx({{
+ if(passesCondition(CcrXcc, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ }
+ }
+ 0x2: Branch22::bicc({{
+ if(passesCondition(CcrIcc, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x3: decode RCOND2
+ {
+ format BranchSplit
+ {
+ 0x1: bpreq({{
+ if(Rs1.sdw == 0)
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x2: bprle({{
+ if(Rs1.sdw <= 0)
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x3: bprl({{
+ if(Rs1.sdw < 0)
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x5: bprne({{
+ if(Rs1.sdw != 0)
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x6: bprg({{
+ if(Rs1.sdw > 0)
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x7: bprge({{
+ if(Rs1.sdw >= 0)
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ }
+ }
+ //SETHI (or NOP if rd == 0 and imm == 0)
+ 0x4: SetHi::sethi({{Rd = imm;}});
+ 0x5: Trap::fbpfcc({{fault = new FpDisabled;}});
+ 0x6: Trap::fbfcc({{fault = new FpDisabled;}});
+ }
+ 0x1: Branch30::call({{
+ R15 = xc->readPC();
+ NNPC = R15 + disp;
+ }});
+ 0x2: decode OP3 {
+ format IntOp {
+ 0x00: add({{Rd = Rs1.sdw + Rs2_or_imm13;}});
+ 0x01: and({{Rd = Rs1.udw & Rs2_or_imm13;}});
+ 0x02: or({{Rd = Rs1.udw | Rs2_or_imm13;}});
+ 0x03: xor({{Rd = Rs1.udw ^ Rs2_or_imm13;}});
+ 0x04: sub({{Rd = Rs1.sdw - Rs2_or_imm13;}});
+ 0x05: andn({{Rd = Rs1.udw & ~Rs2_or_imm13;}});
+ 0x06: orn({{Rd = Rs1.udw | ~Rs2_or_imm13;}});
+ 0x07: xnor({{Rd = ~(Rs1.udw ^ Rs2_or_imm13);}});
+ 0x08: addc({{Rd = Rs1.sdw + Rs2_or_imm13 + CcrIccC;}});
+ 0x09: mulx({{Rd = Rs1 * Rs2_or_imm13;}});
+ 0x0A: umul({{
+ Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>;
+ YValue = Rd<63:32>;
+ }});
+ 0x0B: smul({{
+ Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>;
+ YValue = Rd.sdw;
+ }});
+ 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 + CcrIccC;}});
+ 0x0D: udivx({{
+ if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
+ else Rd.udw = Rs1.udw / Rs2_or_imm13;
+ }});
+ 0x0E: udiv({{
+ if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
+ else
{
- 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;
+ Rd.udw = ((YValue << 32) | Rs1.udw<31:0>) / Rs2_or_imm13;
+ if(Rd.udw >> 32 != 0)
+ Rd.udw = 0xFFFFFFFF;
}
- }});//BPcc
- 0x2: Branch::bicc({{
- if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2))
- ;//branchHere
- }});//Bicc
- 0x3: Branch::bpr({{
- switch(RCOND)
+ }});
+ 0x0F: sdiv({{
+ if(Rs2_or_imm13 == 0)
+ fault = new DivisionByZero;
+ else
{
- 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;
+ Rd.udw = ((YValue << 32) | Rs1.sdw<31:0>) / Rs2_or_imm13;
+ if(Rd.udw<63:31> != 0)
+ Rd.udw = 0x7FFFFFFF;
+ else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF)
+ Rd.udw = 0xFFFFFFFF80000000ULL;
}
- }}); //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;
+ format IntOpCc {
+ 0x10: addcc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ Rd = resTemp = Rs1 + val2;}},
+ {{(Rs1<31:0> + val2<31:0>)<32:>}},
+ {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
+ {{(Rs1<63:1> + val2<63:1> + (Rs1 & val2)<0:>)<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );
+ 0x11: IntOpCcRes::andcc({{Rd = Rs1 & Rs2_or_imm13;}});
+ 0x12: IntOpCcRes::orcc({{Rd = Rs1 | Rs2_or_imm13;}});
+ 0x13: IntOpCcRes::xorcc({{Rd = Rs1 ^ Rs2_or_imm13;}});
+ 0x14: subcc({{
+ int64_t val2 = Rs2_or_imm13;
+ Rd = Rs1 - val2;}},
+ {{(~(Rs1<31:0> + (~val2)<31:0> + 1))<32:>}},
+ {{(Rs1<31:> != val2<31:>) && (Rs1<31:> != Rd<31:>)}},
+ {{(~(Rs1<63:1> + (~val2)<63:1> +
+ (Rs1 | ~val2)<0:>))<63:>}},
+ {{Rs1<63:> != val2<63:> && Rs1<63:> != Rd<63:>}}
+ );
+ 0x15: IntOpCcRes::andncc({{Rd = Rs1 & ~Rs2_or_imm13;}});
+ 0x16: IntOpCcRes::orncc({{Rd = Rs1 | ~Rs2_or_imm13;}});
+ 0x17: IntOpCcRes::xnorcc({{Rd = ~(Rs1 ^ Rs2_or_imm13);}});
+ 0x18: addccc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ int64_t carryin = CcrIccC;
+ Rd = resTemp = Rs1 + val2 + carryin;}},
+ {{(Rs1<31:0> + val2<31:0> + carryin)<32:>}},
+ {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
+ {{(Rs1<63:1> + val2<63:1> +
+ ((Rs1 & val2) | (carryin & (Rs1 | val2)))<0:>)<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );
+ 0x1A: umulcc({{
+ uint64_t resTemp, val2 = Rs2_or_imm13;
+ Rd = resTemp = Rs1.udw<31:0> * val2<31:0>;
+ YValue = resTemp<63:32>;}},
+ {{0}},{{0}},{{0}},{{0}});
+ 0x1B: smulcc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ Rd = resTemp = Rs1.sdw<31:0> * val2<31:0>;
+ YValue = resTemp<63:32>;}},
+ {{0}},{{0}},{{0}},{{0}});
+ 0x1C: subccc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ int64_t carryin = CcrIccC;
+ Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}},
+ {{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}},
+ {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
+ {{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}},
+ {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
+ );
+ 0x1D: udivxcc({{
+ if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
+ else Rd = Rs1.udw / Rs2_or_imm13;}}
+ ,{{0}},{{0}},{{0}},{{0}});
+ 0x1E: udivcc({{
+ uint32_t resTemp, val2 = Rs2_or_imm13;
+ int32_t overflow;
+ if(val2 == 0) fault = new DivisionByZero;
+ else
+ {
+ resTemp = (uint64_t)((YValue << 32) | Rs1.udw<31:0>) / val2;
+ overflow = (resTemp<63:32> != 0);
+ if(overflow) Rd = resTemp = 0xFFFFFFFF;
+ else Rd = resTemp;
+ } }},
+ {{0}},
+ {{overflow}},
+ {{0}},
+ {{0}}
+ );
+ 0x1F: sdivcc({{
+ int32_t resTemp, val2 = Rs2_or_imm13;
+ int32_t overflow, underflow;
+ if(val2 == 0) fault = new DivisionByZero;
+ else
+ {
+ Rd = resTemp = (int64_t)((YValue << 32) | Rs1.sdw<31:0>) / val2;
+ overflow = (resTemp<63:31> != 0);
+ underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF);
+ if(overflow) Rd = resTemp = 0x7FFFFFFF;
+ else if(underflow) Rd = resTemp = 0xFFFFFFFF80000000ULL;
+ else Rd = resTemp;
+ } }},
+ {{0}},
+ {{overflow || underflow}},
+ {{0}},
+ {{0}}
+ );
+ 0x20: taddcc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ 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:>}}
+ );
+ 0x21: tsubcc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ 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:>}}
+ );
+ 0x22: taddcctv({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ Rd = resTemp = Rs1 + val2;
+ int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
+ if(overflow) fault = new TagOverflow;}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{overflow}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );
+ 0x23: tsubcctv({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ Rd = resTemp = Rs1 + val2;
+ int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
+ if(overflow) fault = new TagOverflow;}},
+ {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{overflow}},
+ {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
+ {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
+ );
+ 0x24: mulscc({{
+ int64_t resTemp, multiplicand = Rs2_or_imm13;
+ int32_t multiplier = Rs1<31:0>;
+ int32_t savedLSB = Rs1<0:>;
+ multiplier = multiplier<31:1> |
+ ((CcrIccN
+ ^ CcrIccV) << 32);
+ if(!YValue<0:>)
+ multiplicand = 0;
+ Rd = resTemp = multiplicand + multiplier;
+ YValue = YValue<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:>}}
+ );
+ }
+ format IntOp
+ {
+ 0x25: decode X {
+ 0x0: sll({{Rd = Rs1 << (I ? SHCNT32 : Rs2<4:0>);}});
+ 0x1: sllx({{Rd = Rs1 << (I ? SHCNT64 : Rs2<5:0>);}});
+ }
+ 0x26: decode X {
+ 0x0: srl({{Rd = Rs1.uw >> (I ? SHCNT32 : Rs2<4:0>);}});
+ 0x1: srlx({{Rd = Rs1.udw >> (I ? SHCNT64 : Rs2<5:0>);}});
+ }
+ 0x27: decode X {
+ 0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}});
+ 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
+ }
+ 0x28: decode RS1 {
+ 0x0: rdy({{Rd = YValue;}});
+ 0x2: rdccr({{Rd = Ccr;}});
+ 0x3: rdasi({{Rd = Asi;}});
+ 0x4: PrivTick::rdtick({{Rd = Tick;}});
+ 0x5: rdpc({{Rd = xc->readPC();}});
+ 0x6: rdfprs({{Rd = Fprs;}});
+ 0xF: decode I {
+ 0x0: Nop::membar({{/*Membar isn't needed yet*/}});
+ 0x1: Nop::stbar({{/*Stbar isn't needed yet*/}});
+ }
+ }
+ 0x2A: decode RS1 {
+ format Priv
+ {
+ 0x0: rdprtpc({{
+ Rd = xc->readMiscReg(MISCREG_TPC_BASE + Tl);
+ }});
+ 0x1: rdprtnpc({{
+ Rd = xc->readMiscReg(MISCREG_TNPC_BASE + Tl);
+ }});
+ 0x2: rdprtstate({{
+ Rd = xc->readMiscReg(MISCREG_TSTATE_BASE + Tl);
+ }});
+ 0x3: rdprtt({{
+ Rd = xc->readMiscReg(MISCREG_TT_BASE + Tl);
+ }});
+ 0x4: rdprtick({{Rd = Tick;}});
+ 0x5: rdprtba({{Rd = Tba;}});
+ 0x6: rdprpstate({{Rd = Pstate;}});
+ 0x7: rdprtl({{Rd = Tl;}});
+ 0x8: rdprpil({{Rd = Pil;}});
+ 0x9: rdprcwp({{Rd = Cwp;}});
+ 0xA: rdprcansave({{Rd = Cansave;}});
+ 0xB: rdprcanrestore({{Rd = Canrestore;}});
+ 0xC: rdprcleanwin({{Rd = Cleanwin;}});
+ 0xD: rdprotherwin({{Rd = Otherwin;}});
+ 0xE: rdprwstate({{Rd = Wstate;}});
+ }
+ //The floating point queue isn't implemented right now.
+ 0xF: Trap::rdprfq({{fault = new IllegalInstruction;}});
+ 0x1F: Priv::rdprver({{Rd = Ver;}});
+ }
+ 0x2B: BasicOperate::flushw({{
+ if(NWindows - 2 - Cansave == 0)
+ {
+ if(Otherwin)
+ fault = new SpillNOther(WstateOther);
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;
+ fault = new SpillNNormal(WstateNormal);
+ }
+ }});
+ 0x2C: decode MOVCC3
+ {
+ 0x0: Trap::movccfcc({{fault = new FpDisabled;}});
+ 0x1: decode CC
+ {
+ 0x0: movcci({{
+ if(passesCondition(CcrIcc, COND4))
+ Rd = Rs2_or_imm11;
+ else
+ Rd = Rd;
+ }});
+ 0x2: movccx({{
+ if(passesCondition(CcrXcc, COND4))
+ Rd = Rs2_or_imm11;
+ else
+ Rd = Rd;
+ }});
+ }
+ }
+ 0x2D: sdivx({{
+ if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
+ else Rd.sdw = Rs1.sdw / Rs2_or_imm13;
+ }});
+ 0x2E: decode RS1 {
+ 0x0: IntOp::popc({{
+ int64_t count = 0;
+ uint64_t temp = Rs2_or_imm13;
+ //Count the 1s in the front 4bits until none are left
+ uint8_t oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
+ while(temp)
+ {
+ count += oneBits[temp & 0xF];
+ temp = temp >> 4;
+ }
+ Rd = count;
+ }});
+ }
+ 0x2F: decode RCOND3
+ {
+ 0x1: movreq({{Rd = (Rs1 == 0) ? Rs2_or_imm10 : Rd;}});
+ 0x2: movrle({{Rd = (Rs1 <= 0) ? Rs2_or_imm10 : Rd;}});
+ 0x3: movrl({{Rd = (Rs1 < 0) ? Rs2_or_imm10 : Rd;}});
+ 0x5: movrne({{Rd = (Rs1 != 0) ? Rs2_or_imm10 : Rd;}});
+ 0x6: movrg({{Rd = (Rs1 > 0) ? Rs2_or_imm10 : Rd;}});
+ 0x7: movrge({{Rd = (Rs1 >= 0) ? Rs2_or_imm10 : Rd;}});
+ }
+ 0x30: decode RD {
+ 0x0: wry({{Y = Rs1 ^ Rs2_or_imm13;}});
+ 0x2: wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}});
+ 0x3: wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}});
+ 0x6: wrfprs({{Asi = Rs1 ^ Rs2_or_imm13;}});
+ 0xF: Trap::sir({{fault = new SoftwareInitiatedReset;}});
+ }
+ 0x31: decode FCN {
+ 0x0: BasicOperate::saved({{/*Boogy Boogy*/}});
+ 0x1: BasicOperate::restored({{/*Boogy Boogy*/}});
+ }
+ 0x32: decode RD {
+ format Priv
+ {
+ 0x0: wrprtpc({{
+ xc->setMiscReg(MISCREG_TPC_BASE + Tl,
+ Rs1 ^ Rs2_or_imm13);
+ }});
+ 0x1: wrprtnpc({{
+ xc->setMiscReg(MISCREG_TNPC_BASE + Tl,
+ Rs1 ^ Rs2_or_imm13);
+ }});
+ 0x2: wrprtstate({{
+ xc->setMiscReg(MISCREG_TSTATE_BASE + Tl,
+ Rs1 ^ Rs2_or_imm13);
+ }});
+ 0x3: wrprtt({{
+ xc->setMiscReg(MISCREG_TT_BASE + Tl,
+ Rs1 ^ Rs2_or_imm13);
+ }});
+ 0x4: wrprtick({{Tick = Rs1 ^ Rs2_or_imm13;}});
+ 0x5: wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}});
+ 0x6: wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}});
+ 0x7: wrprtl({{Tl = Rs1 ^ Rs2_or_imm13;}});
+ 0x8: wrprpil({{Pil = Rs1 ^ Rs2_or_imm13;}});
+ 0x9: wrprcwp({{Cwp = Rs1 ^ Rs2_or_imm13;}});
+ 0xA: wrprcansave({{Cansave = Rs1 ^ Rs2_or_imm13;}});
+ 0xB: wrprcanrestore({{Canrestore = Rs1 ^ Rs2_or_imm13;}});
+ 0xC: wrprcleanwin({{Cleanwin = Rs1 ^ Rs2_or_imm13;}});
+ 0xD: wrprotherwin({{Otherwin = Rs1 ^ Rs2_or_imm13;}});
+ 0xE: wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}});
+ }
+ }
+ 0x34: Trap::fpop1({{fault = new FpDisabled;}});
+ 0x35: Trap::fpop2({{fault = new FpDisabled;}});
+ 0x38: Branch::jmpl({{
+ Addr target = Rs1 + Rs2_or_imm13;
+ if(target & 0x3)
+ fault = new MemAddressNotAligned;
+ else
+ {
+ Rd = xc->readPC();
+ NNPC = target;
+ }
+ }});
+ 0x39: Branch::return({{
+ //If both MemAddressNotAligned and
+ //a fill trap happen, it's not clear
+ //which one should be returned.
+ Addr target = Rs1 + Rs2_or_imm13;
+ if(target & 0x3)
+ fault = new MemAddressNotAligned;
+ else
+ NNPC = target;
+ if(fault == NoFault)
+ {
+ //CWP should be set directly so that it always happens
+ //Also, this will allow writing to the new window and
+ //reading from the old one
+ Cwp = (Cwp - 1 + NWindows) % NWindows;
+ if(Canrestore == 0)
+ {
+ if(Otherwin)
+ fault = new FillNOther(WstateOther);
+ else
+ fault = new FillNNormal(WstateNormal);
+ }
+ else
+ {
+ Rd = Rs1 + Rs2_or_imm13;
+ Cansave = Cansave + 1;
+ Canrestore = Canrestore - 1;
+ }
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
+ }
+ }});
+ 0x3A: decode CC
+ {
+ 0x0: Trap::tcci({{
+ if(passesCondition(CcrIcc, COND2))
+ {
+ int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
+ DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
+#if FULL_SYSTEM
+ fault = new TrapInstruction(lTrapNum);
+#else
+ DPRINTF(Sparc, "The syscall number is %d\n", R1);
+ xc->syscall(R1);
+#endif
+ }
else
- rd.udw = resTemp;
- }});//SDIV
+ {
+ DPRINTF(Sparc, "Didn't fire on %s\n", CondTestAbbrev[machInst<25:28>]);
+ }
+ }});
+ 0x2: Trap::tccx({{
+ if(passesCondition(CcrXcc, COND2))
+ {
+ int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
+ DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
+#if FULL_SYSTEM
+ fault = new TrapInstruction(lTrapNum);
+#else
+ DPRINTF(Sparc, "The syscall number is %d\n", R1);
+ xc->syscall(R1);
+#endif
+ }
+ }});
}
- 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
+ 0x3B: Nop::flush({{/*Instruction memory flush*/}});
+ 0x3C: save({{
+ //CWP should be set directly so that it always happens
+ //Also, this will allow writing to the new window and
+ //reading from the old one
+ if(Cansave == 0)
+ {
+ if(Otherwin)
+ fault = new SpillNOther(WstateOther);
+ else
+ fault = new SpillNNormal(WstateNormal);
+ Cwp = (Cwp + 2) % NWindows;
}
- format IntegerOp
+ else if(Cleanwin - Canrestore == 0)
{
- 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
- }
+ Cwp = (Cwp + 1) % NWindows;
+ fault = new CleanWindow;
}
- }
- 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
+ else
+ {
+ Cwp = (Cwp + 1) % NWindows;
+ Rd = Rs1 + Rs2_or_imm13;
+ Cansave = Cansave - 1;
+ Canrestore = Canrestore + 1;
+ }
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
+ }});
+ 0x3D: restore({{
+ //CWP should be set directly so that it always happens
+ //Also, this will allow writing to the new window and
+ //reading from the old one
+ Cwp = (Cwp - 1 + NWindows) % NWindows;
+ if(Canrestore == 0)
+ {
+ if(Otherwin)
+ fault = new FillNOther(WstateOther);
+ else
+ fault = new FillNNormal(WstateNormal);
+ }
+ else
+ {
+ Rd = Rs1 + Rs2_or_imm13;
+ Cansave = Cansave + 1;
+ Canrestore = Canrestore - 1;
}
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
+ }});
+ 0x3E: decode FCN {
+ 0x0: Priv::done({{
+ if(Tl == 0)
+ return new IllegalInstruction;
+ Cwp = xc->readMiscReg(MISCREG_TSTATE_CWP_BASE + Tl);
+ Asi = xc->readMiscReg(MISCREG_TSTATE_ASI_BASE + Tl);
+ Ccr = xc->readMiscReg(MISCREG_TSTATE_CCR_BASE + Tl);
+ Pstate = xc->readMiscReg(MISCREG_TSTATE_PSTATE_BASE + Tl);
+ NPC = xc->readMiscReg(MISCREG_TNPC_BASE + Tl);
+ NNPC = NPC + 4;
+ Tl = Tl - 1;
+ }});
+ 0x1: BasicOperate::retry({{
+ if(Tl == 0)
+ return new IllegalInstruction;
+ Cwp = xc->readMiscReg(MISCREG_TSTATE_CWP_BASE + Tl);
+ Asi = xc->readMiscReg(MISCREG_TSTATE_ASI_BASE + Tl);
+ Ccr = xc->readMiscReg(MISCREG_TSTATE_CCR_BASE + Tl);
+ Pstate = xc->readMiscReg(MISCREG_TSTATE_PSTATE_BASE + Tl);
+ NPC = xc->readMiscReg(MISCREG_TPC_BASE + Tl);
+ NNPC = xc->readMiscReg(MISCREG_TNPC_BASE + Tl);
+ Tl = Tl - 1;
+ }});
+ }
+ }
+ }
+ 0x3: decode OP3 {
+ format Load {
+ 0x00: lduw({{Rd = Mem;}}, {{32}});
+ 0x01: ldub({{Rd = Mem;}}, {{8}});
+ 0x02: lduh({{Rd = Mem;}}, {{16}});
+ 0x03: ldd({{
+ uint64_t val = Mem;
+ RdLow = val<31:0>;
+ RdHigh = val<63:32>;
+ }}, {{64}});
+ }
+ format Store {
+ 0x04: stw({{Mem = Rd.sw;}}, {{32}});
+ 0x05: stb({{Mem = Rd.sb;}}, {{8}});
+ 0x06: sth({{Mem = Rd.shw;}}, {{16}});
+ 0x07: std({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}});
+ }
+ format Load {
+ 0x08: ldsw({{Rd = (int32_t)Mem;}}, {{32}});
+ 0x09: ldsb({{Rd = (int8_t)Mem;}}, {{8}});
+ 0x0A: ldsh({{Rd = (int16_t)Mem;}}, {{16}});
+ 0x0B: ldx({{Rd = (int64_t)Mem;}}, {{64}});
+ 0x0D: ldstub({{
+ Rd = Mem;
+ Mem = 0xFF;
+ }}, {{8}});
+ }
+ 0x0E: Store::stx({{Mem = Rd}}, {{64}});
+ 0x0F: LoadStore::swap({{
+ uint32_t temp = Rd;
+ Rd = Mem;
+ Mem = temp;
+ }}, {{32}});
+ format Load {
+ 0x10: lduwa({{Rd = Mem;}}, {{32}});
+ 0x11: lduba({{Rd = Mem;}}, {{8}});
+ 0x12: lduha({{Rd = Mem;}}, {{16}});
+ 0x13: ldda({{
+ uint64_t val = Mem;
+ RdLow = val<31:0>;
+ RdHigh = val<63:32>;
+ }}, {{64}});
+ }
+ format Store {
+ 0x14: stwa({{Mem = Rd;}}, {{32}});
+ 0x15: stba({{Mem = Rd;}}, {{8}});
+ 0x16: stha({{Mem = Rd;}}, {{16}});
+ 0x17: stda({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}});
+ }
+ format Load {
+ 0x18: ldswa({{Rd = (int32_t)Mem;}}, {{32}});
+ 0x19: ldsba({{Rd = (int8_t)Mem;}}, {{8}});
+ 0x1A: ldsha({{Rd = (int16_t)Mem;}}, {{16}});
+ 0x1B: ldxa({{Rd = (int64_t)Mem;}}, {{64}});
+ }
+ 0x1D: LoadStore::ldstuba({{
+ Rd = Mem;
+ Mem = 0xFF;
+ }}, {{8}});
+ 0x1E: Store::stxa({{Mem = Rd}}, {{64}});
+ 0x1F: LoadStore::swapa({{
+ uint32_t temp = Rd;
+ Rd = Mem;
+ Mem = temp;
+ }}, {{32}});
+ format Trap {
+ 0x20: ldf({{fault = new FpDisabled;}});
+ 0x21: decode X {
+ 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}});
+ 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}});
+ }
+ 0x22: ldqf({{fault = new FpDisabled;}});
+ 0x23: lddf({{fault = new FpDisabled;}});
+ 0x24: stf({{fault = new FpDisabled;}});
+ 0x25: decode X {
+ 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}});
+ 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}});
+ }
+ 0x26: stqf({{fault = new FpDisabled;}});
+ 0x27: stdf({{fault = new FpDisabled;}});
+ 0x2D: Nop::prefetch({{ }});
+ 0x30: ldfa({{return new FpDisabled;}});
+ 0x32: ldqfa({{fault = new FpDisabled;}});
+ 0x33: lddfa({{fault = new FpDisabled;}});
+ 0x34: stfa({{fault = new FpDisabled;}});
+ 0x35: stqfa({{fault = new FpDisabled;}});
+ 0x36: stdfa({{fault = new FpDisabled;}});
+ 0x3C: Cas::casa({{
+ uint64_t val = Mem.uw;
+ if(Rs2.uw == val)
+ Mem.uw = Rd.uw;
+ Rd.uw = val;
+ }});
+ 0x3D: Nop::prefetcha({{ }});
+ 0x3E: Cas::casxa({{
+ uint64_t val = Mem.udw;
+ if(Rs2 == val)
+ Mem.udw = Rd;
+ Rd = val;
+ }});
}
+ }
}
diff --git a/arch/sparc/isa/formats.isa b/arch/sparc/isa/formats.isa
index 547f8be48..17d68061b 100644
--- a/arch/sparc/isa/formats.isa
+++ b/arch/sparc/isa/formats.isa
@@ -1,19 +1,28 @@
//Include the basic format
//Templates from this format are used later
-##include "m5/arch/sparc/isa/formats/basic.isa"
+##include "formats/basic.isa"
+
+//Include the noop format
+##include "formats/nop.isa"
//Include the integerOp and integerOpCc format
-##include "m5/arch/sparc/isa/formats/integerop.isa"
+##include "formats/integerop.isa"
-//Include the mem format
-##include "m5/arch/sparc/isa/formats/mem.isa"
+//Include the memory format
+##include "formats/mem.isa"
+
+//Include the compare and swap format
+##include "formats/cas.isa"
//Include the trap format
-##include "m5/arch/sparc/isa/formats/trap.isa"
+##include "formats/trap.isa"
-//Include the branch format
-##include "m5/arch/sparc/isa/formats/branch.isa"
+//Include the "unknown" format
+##include "formats/unknown.isa"
-//Include the noop format
-##include "m5/arch/sparc/isa/formats/noop.isa"
+//Include the priveleged mode format
+##include "formats/priv.isa"
+
+//Include the branch format
+##include "formats/branch.isa"
diff --git a/arch/sparc/isa/formats/branch.isa b/arch/sparc/isa/formats/branch.isa
index 80101de1b..37bdb9402 100644
--- a/arch/sparc/isa/formats/branch.isa
+++ b/arch/sparc/isa/formats/branch.isa
@@ -5,7 +5,7 @@
output header {{
/**
- * Base class for integer operations.
+ * Base class for branch operations.
*/
class Branch : public SparcStaticInst
{
@@ -19,12 +19,187 @@ output header {{
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
};
+
+ /**
+ * Base class for branch operations with an immediate displacement.
+ */
+ class BranchDisp : public Branch
+ {
+ protected:
+ // Constructor
+ BranchDisp(const char *mnem, MachInst _machInst,
+ OpClass __opClass) :
+ Branch(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ int32_t disp;
+ };
+
+ /**
+ * Base class for branches with 19 bit displacements.
+ */
+ class Branch19 : public BranchDisp
+ {
+ protected:
+ // Constructor
+ Branch19(const char *mnem, MachInst _machInst,
+ OpClass __opClass) :
+ BranchDisp(mnem, _machInst, __opClass)
+ {
+ disp = sign_ext(DISP19 << 2, 21);
+ }
+ };
+
+ /**
+ * Base class for branches with 22 bit displacements.
+ */
+ class Branch22 : public BranchDisp
+ {
+ protected:
+ // Constructor
+ Branch22(const char *mnem, MachInst _machInst,
+ OpClass __opClass) :
+ BranchDisp(mnem, _machInst, __opClass)
+ {
+ disp = sign_ext(DISP22 << 2, 24);
+ }
+ };
+
+ /**
+ * Base class for branches with 30 bit displacements.
+ */
+ class Branch30 : public BranchDisp
+ {
+ protected:
+ // Constructor
+ Branch30(const char *mnem, MachInst _machInst,
+ OpClass __opClass) :
+ BranchDisp(mnem, _machInst, __opClass)
+ {
+ disp = sign_ext(DISP30 << 2, 32);
+ }
+ };
+
+ /**
+ * Base class for 16bit split displacements.
+ */
+ class BranchSplit : public BranchDisp
+ {
+ protected:
+ // Constructor
+ BranchSplit(const char *mnem, MachInst _machInst,
+ OpClass __opClass) :
+ BranchDisp(mnem, _machInst, __opClass)
+ {
+ disp = sign_ext((D16HI << 16) | (D16LO << 2), 18);
+ }
+ };
+
+ /**
+ * Base class for branches that use an immediate and a register to
+ * compute their displacements.
+ */
+ class BranchImm13 : public Branch
+ {
+ protected:
+ // Constructor
+ BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13))
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ int32_t imm;
+ };
}};
output decoder {{
- std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ std::string Branch::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+
+ if (_numSrcRegs > 0)
+ {
+ printReg(response, _srcRegIdx[0]);
+ for(int x = 1; x < _numSrcRegs; x++)
+ {
+ response << ", ";
+ printReg(response, _srcRegIdx[x]);
+ }
+ }
+
+ if (_numDestRegs > 0)
+ {
+ if(_numSrcRegs > 0)
+ response << ", ";
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+ std::string BranchImm13::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+
+ if (_numSrcRegs > 0)
+ {
+ printReg(response, _srcRegIdx[0]);
+ for(int x = 1; x < _numSrcRegs; x++)
+ {
+ response << ", ";
+ printReg(response, _srcRegIdx[x]);
+ }
+ }
+
+ if(_numSrcRegs > 0)
+ response << ", ";
+
+ ccprintf(response, "0x%x", imm);
+
+ if (_numDestRegs > 0)
+ {
+ response << ", ";
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+ std::string BranchDisp::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
- return "Branch instruction\n";
+ std::stringstream response;
+ std::string symbol;
+ Addr symbolAddr;
+
+ Addr target = disp + pc;
+
+ printMnemonic(response, mnemonic);
+ ccprintf(response, "0x%x", target);
+
+ if(symtab->findNearestSymbol(target, symbol, symbolAddr))
+ {
+ ccprintf(response, " <%s", symbol);
+ if(symbolAddr != target)
+ ccprintf(response, "+%d>", target - symbolAddr);
+ else
+ ccprintf(response, ">");
+ }
+
+ return response.str();
}
}};
@@ -34,10 +209,11 @@ def template BranchExecute {{
{
//Attempt to execute the instruction
Fault fault = NoFault;
- checkPriv;
%(op_decl)s;
%(op_rd)s;
+
+ NNPC = xc->readNextNPC();
%(code)s;
if(fault == NoFault)
@@ -50,13 +226,83 @@ def template BranchExecute {{
}
}};
-// Primary format for integer operate instructions:
+let {{
+ handle_annul = '''
+ {
+ if(A)
+ {
+ NPC = xc->readNextNPC();
+ NNPC = NPC + 4;
+ }
+ else
+ {
+ NPC = xc->readNextPC();
+ NNPC = xc->readNextNPC();
+ }
+ }'''
+}};
+
+// Primary format for branch instructions:
def format Branch(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
+ code = re.sub(r'handle_annul', handle_annul, code)
+ (usesImm, code, immCode,
+ rString, iString) = splitOutImm(code)
+ iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BranchExecute.subst(iop)
+ if usesImm:
+ imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
+ immCode, opt_flags)
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += BranchExecute.subst(imm_iop)
+ decode_block = ROrImmDecode.subst(iop)
+ else:
+ decode_block = BasicDecode.subst(iop)
+}};
+
+// Primary format for branch instructions:
+def format Branch19(code, *opt_flags) {{
+ code = re.sub(r'handle_annul', handle_annul, code)
+ codeBlk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BranchExecute.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+}};
+
+// Primary format for branch instructions:
+def format Branch22(code, *opt_flags) {{
+ code = re.sub(r'handle_annul', handle_annul, code)
+ codeBlk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
exec_output = BranchExecute.subst(iop)
+ decode_block = BasicDecode.subst(iop)
}};
+
+// Primary format for branch instructions:
+def format Branch30(code, *opt_flags) {{
+ code = re.sub(r'handle_annul', handle_annul, code)
+ codeBlk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BranchExecute.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+}};
+
+// Primary format for branch instructions:
+def format BranchSplit(code, *opt_flags) {{
+ code = re.sub(r'handle_annul', handle_annul, code)
+ codeBlk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BranchExecute.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+}};
+
diff --git a/arch/sparc/isa/formats/integerop.isa b/arch/sparc/isa/formats/integerop.isa
index 5a9e09896..881154b67 100644
--- a/arch/sparc/isa/formats/integerop.isa
+++ b/arch/sparc/isa/formats/integerop.isa
@@ -7,106 +7,343 @@ output header {{
/**
* Base class for integer operations.
*/
- class IntegerOp : public SparcStaticInst
+ class IntOp : public SparcStaticInst
{
protected:
// Constructor
- IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ IntOp(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
SparcStaticInst(mnem, _machInst, __opClass)
{
}
std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ virtual bool printPseudoOps(std::ostream &os, Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for immediate integer operations.
+ */
+ class IntOpImm : public IntOp
+ {
+ protected:
+ // Constructor
+ IntOpImm(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ IntOp(mnem, _machInst, __opClass)
+ {
+ }
+
+ int32_t imm;
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ virtual bool printPseudoOps(std::ostream &os, Addr pc,
const SymbolTable *symtab) const;
};
+
+ /**
+ * Base class for 10 bit immediate integer operations.
+ */
+ class IntOpImm10 : public IntOpImm
+ {
+ protected:
+ // Constructor
+ IntOpImm10(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ IntOpImm(mnem, _machInst, __opClass)
+ {
+ imm = sign_ext(SIMM10, 10);
+ }
+ };
+
+ /**
+ * Base class for 11 bit immediate integer operations.
+ */
+ class IntOpImm11 : public IntOpImm
+ {
+ protected:
+ // Constructor
+ IntOpImm11(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ IntOpImm(mnem, _machInst, __opClass)
+ {
+ imm = sign_ext(SIMM11, 11);
+ }
+ };
+
+ /**
+ * Base class for 13 bit immediate integer operations.
+ */
+ class IntOpImm13 : public IntOpImm
+ {
+ protected:
+ // Constructor
+ IntOpImm13(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ IntOpImm(mnem, _machInst, __opClass)
+ {
+ imm = sign_ext(SIMM13, 13);
+ }
+ };
+
+ /**
+ * Base class for sethi.
+ */
+ class SetHi : public IntOpImm
+ {
+ protected:
+ // Constructor
+ SetHi(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ IntOpImm(mnem, _machInst, __opClass)
+ {
+ imm = (IMM22 << 10) & 0xFFFFFC00;
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+def template SetHiDecode {{
+ {
+ if(RD == 0 && IMM22 == 0)
+ return (SparcStaticInst *)(new Nop("nop", machInst, No_OpClass));
+ else
+ return (SparcStaticInst *)(new %(class_name)s(machInst));
+ }
}};
output decoder {{
- std::string IntegerOp::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
+
+ bool IntOp::printPseudoOps(std::ostream &os, Addr pc,
+ const SymbolTable *symbab) const
{
- return "Integer instruction\n";
+ if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0)
+ {
+ printMnemonic(os, "mov");
+ if(_numSrcRegs > 0)
+ printReg(os, _srcRegIdx[1]);
+ ccprintf(os, ", ");
+ if(_numDestRegs > 0)
+ printReg(os, _destRegIdx[0]);
+
+ return true;
+ }
+ return false;
}
-}};
-def template IntegerExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ bool IntOpImm::printPseudoOps(std::ostream &os, Addr pc,
+ const SymbolTable *symbab) const
{
- //These are set to constants when the execute method
- //is generated
- bool useCc = ;
- bool checkPriv = ;
-
- //Attempt to execute the instruction
- try
+ if(!strcmp(mnemonic, "or"))
+ {
+ if(_srcRegIdx[0] == 0)
+ {
+ if(imm == 0)
+ {
+ printMnemonic(os, "clr");
+ if(_numDestRegs > 0)
+ printReg(os, _destRegIdx[0]);
+ return true;
+ }
+ else
+ {
+ printMnemonic(os, "mov");
+ ccprintf(os, ", 0x%x, ", imm);
+ if(_numDestRegs > 0)
+ printReg(os, _destRegIdx[0]);
+ return true;
+ }
+ }
+ else if(imm == 0)
{
- checkPriv;
+ printMnemonic(os, "mov");
+ if(_numSrcRegs > 0)
+ printReg(os, _srcRegIdx[0]);
+ ccprintf(os, ", ");
+ if(_numDestRegs > 0)
+ printReg(os, _destRegIdx[0]);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ std::string IntOp::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
+ if(!printPseudoOps(response, pc, symtab))
+ {
+ printMnemonic(response, mnemonic);
+ if (_numSrcRegs > 0)
+ {
+ printReg(response, _srcRegIdx[0]);
+ for(int x = 1; x < _numSrcRegs; x++)
+ {
+ response << ", ";
+ printReg(response, _srcRegIdx[x]);
+ }
}
- //If we have an exception for some reason,
- //deal with it
- catch(SparcException except)
+ if (_numDestRegs > 0)
{
- //Deal with exception
- return No_Fault;
+ if(_numSrcRegs > 0)
+ response << ", ";
+ printReg(response, _destRegIdx[0]);
}
+ }
+ return response.str();
+ }
- //Write the resulting state to the execution context
- %(op_wb)s;
- if(useCc)
+ std::string IntOpImm::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ if(!printPseudoOps(response, pc, symtab))
+ {
+ printMnemonic(response, mnemonic);
+ if (_numSrcRegs > 0)
+ {
+ printReg(response, _srcRegIdx[0]);
+ for(int x = 1; x < _numSrcRegs - 1; x++)
+ {
+ response << ", ";
+ printReg(response, _srcRegIdx[x]);
+ }
+ }
+ if(_numSrcRegs > 0)
+ response << ", ";
+ ccprintf(response, "0x%x", imm);
+ if (_numDestRegs > 0)
{
- 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;
+ response << ", ";
+ printReg(response, _destRegIdx[0]);
}
- return No_Fault;
+ }
+ return response.str();
+ }
+
+ std::string SetHi::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+ if(_numSrcRegs > 0)
+ response << ", ";
+ ccprintf(response, "%%hi(0x%x), ", imm);
+ printReg(response, _destRegIdx[0]);
+ return response.str();
}
}};
-// 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)
+def template IntOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ //Write the resulting state to the execution context
+ if(fault == NoFault)
+ {
+ %(cc_code)s;
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+let {{
+ def doIntFormat(code, ccCode, name, Name, opt_flags):
+ (usesImm, code, immCode,
+ rString, iString) = splitOutImm(code)
+ iop = InstObjParams(name, Name, 'IntOp', code,
+ opt_flags, ("cc_code", ccCode))
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = IntegerExecute.subst(iop)
+ exec_output = IntOpExecute.subst(iop)
+ if usesImm:
+ imm_iop = InstObjParams(name, Name + 'Imm', 'IntOpImm' + iString,
+ immCode, opt_flags, ("cc_code", ccCode))
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += IntOpExecute.subst(imm_iop)
+ decode_block = ROrImmDecode.subst(iop)
+ else:
+ decode_block = BasicDecode.subst(iop)
+ return (header_output, decoder_output, exec_output, decode_block)
+
+ calcCcCode = '''
+ CcrIccN = (Rd >> 31) & 1;
+ CcrIccZ = ((Rd & 0xFFFFFFFF) == 0);
+ CcrXccN = (Rd >> 63) & 1;
+ CcrXccZ = (Rd == 0);
+ CcrIccV = %(ivValue)s;
+ CcrIccC = %(icValue)s;
+ CcrXccV = %(xvValue)s;
+ CcrXccC = %(xcValue)s;
+ DPRINTF(Sparc, "in = %%d\\n", CcrIccN);
+ DPRINTF(Sparc, "iz = %%d\\n", CcrIccZ);
+ DPRINTF(Sparc, "xn = %%d\\n", CcrXccN);
+ DPRINTF(Sparc, "xz = %%d\\n", CcrXccZ);
+ DPRINTF(Sparc, "iv = %%d\\n", CcrIccV);
+ DPRINTF(Sparc, "ic = %%d\\n", CcrIccC);
+ DPRINTF(Sparc, "xv = %%d\\n", CcrXccV);
+ DPRINTF(Sparc, "xc = %%d\\n", CcrXccC);
+ '''
}};
// 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)
+def format IntOp(code, *opt_flags) {{
+ ccCode = ''
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doIntFormat(code, ccCode,
+ name, Name, opt_flags)
+}};
+
+// Primary format for integer operate instructions:
+def format IntOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{
+ ccCode = calcCcCode % vars()
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doIntFormat(code, ccCode,
+ name, Name, opt_flags)
+}};
+
+// Primary format for integer operate instructions:
+def format IntOpCcRes(code, *opt_flags) {{
+ ccCode = calcCcCode % {"icValue":"0",
+ "ivValue":"0",
+ "xcValue":"0",
+ "xvValue":"0"}
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doIntFormat(code, ccCode,
+ name, Name, opt_flags)
}};
+
+def format SetHi(code, *opt_flags) {{
+ iop = InstObjParams(name, Name, 'SetHi',
+ code, opt_flags, ("cc_code", ''))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = IntOpExecute.subst(iop)
+ decode_block = SetHiDecode.subst(iop)
+}};
+
diff --git a/arch/sparc/isa/formats/mem.isa b/arch/sparc/isa/formats/mem.isa
index d72de47d0..12dae57e5 100644
--- a/arch/sparc/isa/formats/mem.isa
+++ b/arch/sparc/isa/formats/mem.isa
@@ -5,14 +5,14 @@
output header {{
/**
- * Base class for integer operations.
+ * Base class for memory operations.
*/
class Mem : public SparcStaticInst
{
protected:
// Constructor
- Mem(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
SparcStaticInst(mnem, _machInst, __opClass)
{
}
@@ -20,12 +20,82 @@ output header {{
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
};
+
+ /**
+ * Class for memory operations which use an immediate offset.
+ */
+ class MemImm : public Mem
+ {
+ protected:
+
+ // Constructor
+ MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ Mem(mnem, _machInst, __opClass)
+ {
+ imm = sign_ext(SIMM13, 13);
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ int32_t imm;
+ };
}};
output decoder {{
- std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ std::string Mem::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ ccprintf(response, " + ");
+ printReg(response, _srcRegIdx[!save ? 1 : 2]);
+ ccprintf(response, " ]");
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+ std::string MemImm::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
- return "Memory instruction\n";
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ if(imm >= 0)
+ ccprintf(response, " + 0x%x ]", imm);
+ else
+ ccprintf(response, " + -0x%x ]", -imm);
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
}
}};
@@ -34,10 +104,14 @@ def template MemExecute {{
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
+ Addr EA;
%(op_decl)s;
%(op_rd)s;
- ea_code
+ %(ea_code)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ %(load)s;
%(code)s;
+ %(store)s;
if(fault == NoFault)
{
@@ -49,25 +123,49 @@ def template MemExecute {{
}
}};
-// 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;');
+let {{
+ # Leave memAccessFlags at 0 for now
+ loadString = "xc->read(EA, (uint%(width)s_t&)Mem, 0);"
+ storeString = "uint64_t write_result = 0; \
+ xc->write((uint%(width)s_t)Mem, EA, 0, &write_result);"
+
+ def doMemFormat(code, load, store, name, Name, opt_flags):
+ addrCalcReg = 'EA = Rs1 + Rs2;'
+ addrCalcImm = 'EA = Rs1 + imm;'
+ iop = InstObjParams(name, Name, 'Mem', code,
+ opt_flags, ("ea_code", addrCalcReg),
+ ("load", load), ("store", store))
+ iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code,
+ opt_flags, ("ea_code", addrCalcImm),
+ ("load", load), ("store", store))
+ header_output = BasicDeclare.subst(iop) + BasicDeclare.subst(iop_imm)
+ decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
+ decode_block = ROrImmDecode.subst(iop)
+ exec_output = MemExecute.subst(iop) + MemExecute.subst(iop_imm)
+ return (header_output, decoder_output, exec_output, decode_block)
+}};
+
+def format Load(code, width, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doMemFormat(code,
+ loadString % {"width":width}, '', name, Name, opt_flags)
+}};
+
+def format Store(code, width, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doMemFormat(code, '',
+ storeString % {"width":width}, name, Name, opt_flags)
}};
-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;');
+def format LoadStore(code, width, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doMemFormat(code,
+ loadString % {"width":width}, storeString % {"width":width},
+ name, Name, opt_flags)
}};
diff --git a/arch/sparc/isa/formats/noop.isa b/arch/sparc/isa/formats/noop.isa
deleted file mode 100644
index fa4047f06..000000000
--- a/arch/sparc/isa/formats/noop.isa
+++ /dev/null
@@ -1,50 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// 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/nop.isa b/arch/sparc/isa/formats/nop.isa
new file mode 100644
index 000000000..df7503eee
--- /dev/null
+++ b/arch/sparc/isa/formats/nop.isa
@@ -0,0 +1,62 @@
+////////////////////////////////////////////////////////////////////
+//
+// Nop instruction
+//
+
+output header {{
+ /**
+ * Nop class.
+ */
+ class Nop : public SparcStaticInst
+ {
+ public:
+ // Constructor
+ Nop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ // All Nop instructions do the same thing, so this can be
+ // defined here. Nops can be defined directly, so there needs
+ // to be a default implementation
+ Fault execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ //Nothing to see here, move along
+ return NoFault;
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ printMnemonic(response, mnemonic);
+ return response.str();
+ }
+}};
+
+def template NopExecute {{
+ 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 Nop(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'Nop', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = NopExecute.subst(iop)
+}};
diff --git a/arch/sparc/isa/formats/priv.isa b/arch/sparc/isa/formats/priv.isa
new file mode 100644
index 000000000..f9fea01f2
--- /dev/null
+++ b/arch/sparc/isa/formats/priv.isa
@@ -0,0 +1,139 @@
+////////////////////////////////////////////////////////////////////
+//
+// Privilege mode instructions
+//
+
+output header {{
+ /**
+ * Base class for privelege mode operations.
+ */
+ class Priv : public SparcStaticInst
+ {
+ protected:
+ // Constructor
+ Priv(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for user mode "tick" access.
+ */
+ class PrivTick : public SparcStaticInst
+ {
+ protected:
+ // Constructor
+ PrivTick(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for privelege mode operations with immediates.
+ */
+ class PrivImm : public Priv
+ {
+ protected:
+ // Constructor
+ PrivImm(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ Priv(mnem, _machInst, __opClass), imm(SIMM13)
+ {
+ }
+
+ int32_t imm;
+ };
+
+ /**
+ * Base class for user mode "tick" access with immediates.
+ */
+ class PrivTickImm : public PrivTick
+ {
+ protected:
+ // Constructor
+ PrivTickImm(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass) :
+ PrivTick(mnem, _machInst, __opClass), imm(SIMM13)
+ {
+ }
+
+ int32_t imm;
+ };
+}};
+
+output decoder {{
+ std::string Priv::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return "Privileged Instruction";
+ }
+
+ std::string PrivTick::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return "Regular access to Tick";
+ }
+}};
+
+def template PrivExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ %(op_decl)s;
+ %(op_rd)s;
+
+ //If the processor isn't in privileged mode, fault out right away
+ if(%(check)s)
+ return new PrivilegedAction;
+
+ %(code)s;
+ %(op_wb)s;
+ return NoFault;
+ }
+}};
+
+let {{
+ def doPrivFormat(code, checkCode, name, Name, opt_flags):
+ (usesImm, code, immCode,
+ rString, iString) = splitOutImm(code)
+ iop = InstObjParams(name, Name, 'Priv', code,
+ opt_flags, ("check", checkCode))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = PrivExecute.subst(iop)
+ if usesImm:
+ imm_iop = InstObjParams(name, Name + 'Imm', 'PrivImm',
+ immCode, opt_flags, ("check", checkCode))
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += PrivExecute.subst(imm_iop)
+ decode_block = ROrImmDecode.subst(iop)
+ else:
+ decode_block = BasicDecode.subst(iop)
+ return (header_output, decoder_output, exec_output, decode_block)
+}};
+
+// Primary format for integer operate instructions:
+def format Priv(code, *opt_flags) {{
+ checkCode = "(!PstatePriv)"
+ (header_output, decoder_output,
+ exec_output, decode_block) = doPrivFormat(code,
+ checkCode, name, Name, opt_flags)
+}};
+
+// Primary format for integer operate instructions:
+def format PrivTick(code, *opt_flags) {{
+ checkCode = "(!PstatePriv && TickNpt)"
+ (header_output, decoder_output,
+ exec_output, decode_block) = doPrivFormat(code,
+ checkCode, name, Name, opt_flags)
+}};
diff --git a/arch/sparc/isa/formats/trap.isa b/arch/sparc/isa/formats/trap.isa
index ff3aadf72..f6a45ca48 100644
--- a/arch/sparc/isa/formats/trap.isa
+++ b/arch/sparc/isa/formats/trap.isa
@@ -5,20 +5,23 @@
output header {{
/**
- * Base class for integer operations.
+ * Base class for trap instructions,
+ * or instructions that always fault.
*/
class Trap : public SparcStaticInst
{
protected:
// Constructor
- Trap(const char *mnem, MachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
+ Trap(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass), trapNum(SW_TRAP)
{
}
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
+
+ int trapNum;
};
}};
@@ -26,7 +29,15 @@ output decoder {{
std::string Trap::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
- return "Trap instruction\n";
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+ ccprintf(response, " ");
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", 0x%x", trapNum);
+ ccprintf(response, ", or ");
+ printReg(response, _srcRegIdx[1]);
+ return response.str();
}
}};
@@ -34,18 +45,20 @@ 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;
+ Fault fault = NoFault;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s
+ return fault;
}
}};
-// Primary format for integer operate instructions:
def format Trap(code, *opt_flags) {{
orig_code = code
cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
+ iop = InstObjParams(name, Name, 'Trap', cblk, opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
+ decode_block = BasicDecode.subst(iop)
exec_output = TrapExecute.subst(iop)
}};
diff --git a/arch/sparc/isa/formats/unknown.isa b/arch/sparc/isa/formats/unknown.isa
new file mode 100644
index 000000000..223111905
--- /dev/null
+++ b/arch/sparc/isa/formats/unknown.isa
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////
+//
+// Unknown instructions
+//
+
+output header {{
+ /**
+ * Class for Unknown/Illegal instructions
+ */
+ class Unknown : public SparcStaticInst
+ {
+ public:
+
+ // Constructor
+ Unknown(ExtMachInst _machInst) :
+ SparcStaticInst("unknown", _machInst, No_OpClass)
+ {
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ };
+}};
+
+output decoder {{
+ std::string Unknown::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return "Unknown instruction";
+ }
+}};
+
+output exec {{
+ Fault Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ return new IllegalInstruction;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
diff --git a/arch/sparc/isa/includes.isa b/arch/sparc/isa/includes.isa
index a99018b49..ff4174899 100644
--- a/arch/sparc/isa/includes.isa
+++ b/arch/sparc/isa/includes.isa
@@ -10,8 +10,9 @@ output header {{
#include "cpu/static_inst.hh"
#include "arch/sparc/faults.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
+#include "mem/request.hh" // some constructors use MemReq flags
#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/regfile.hh"
}};
output decoder {{
@@ -34,10 +35,12 @@ output exec {{
#endif
#ifdef FULL_SYSTEM
-//#include "arch/alpha/pseudo_inst.hh"
+//#include "sim/pseudo_inst.hh"
#endif
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "sim/sim_exit.hh"
+
+using namespace SparcISA;
}};
diff --git a/arch/sparc/isa/main.isa b/arch/sparc/isa/main.isa
index ab0290d58..35167d6b7 100644
--- a/arch/sparc/isa/main.isa
+++ b/arch/sparc/isa/main.isa
@@ -26,7 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-##include "m5/arch/sparc/isa/includes.isa"
+##include "includes.isa"
////////////////////////////////////////////////////////////////////
//
@@ -37,16 +37,16 @@
namespace SparcISA;
//Include the bitfield definitions
-##include "m5/arch/sparc/isa/bitfields.isa"
+##include "bitfields.isa"
//Include the operand_types and operand definitions
-##include "m5/arch/sparc/isa/operands.isa"
+##include "operands.isa"
//Include the base class for sparc instructions, and some support code
-##include "m5/arch/sparc/isa/base.isa"
+##include "base.isa"
//Include the definitions for the instruction formats
-##include "m5/arch/sparc/isa/formats.isa"
+##include "formats.isa"
//Include the decoder definition
-##include "m5/arch/sparc/isa/decoder.isa"
+##include "decoder.isa"
diff --git a/arch/sparc/isa/operands.isa b/arch/sparc/isa/operands.isa
index 64f5abd08..64a032eea 100644
--- a/arch/sparc/isa/operands.isa
+++ b/arch/sparc/isa/operands.isa
@@ -16,16 +16,100 @@ 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),
+ 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
+ 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2),
+ 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
+ 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
+ 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
#'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),
+ 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 4),
+ 'NNPC': ('NNPC', 'udw', 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)
+ 'R0': ('IntReg', 'udw', '0', None, 6),
+ 'R1': ('IntReg', 'udw', '1', None, 7),
+ 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
+ 'R16': ('IntReg', 'udw', '16', None, 9),
+ # Control registers
+ 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1),
+ 'PstateAg': ('ControlReg', 'udw', 'MISCREG_PSTATE_AG', None, 2),
+ 'PstateIe': ('ControlReg', 'udw', 'MISCREG_PSTATE_IE', None, 3),
+ 'PstatePriv': ('ControlReg', 'udw', 'MISCREG_PSTATE_PRIV', None, 4),
+ 'PstateAm': ('ControlReg', 'udw', 'MISCREG_PSTATE_AM', None, 5),
+ 'PstatePef': ('ControlReg', 'udw', 'MISCREG_PSTATE_PEF', None, 6),
+ 'PstateRed': ('ControlReg', 'udw', 'MISCREG_PSTATE_RED', None, 7),
+ 'PstateMm': ('ControlReg', 'udw', 'MISCREG_PSTATE_MM', None, 8),
+ 'PstateTle': ('ControlReg', 'udw', 'MISCREG_PSTATE_TLE', None, 9),
+ 'PstateCle': ('ControlReg', 'udw', 'MISCREG_PSTATE_CLE', None, 10),
+ 'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 11),
+ 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 12),
+ 'YValue': ('ControlReg', 'udw', 'MISCREG_Y_VALUE', None, 13),
+ 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 14),
+ 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 15),
+ #'Tt': ('ControlReg', 'udw', 'MISCREG_TT_BASE + tl', None, 16),
+ 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 17),
+ 'CcrIcc': ('ControlReg', 'udw', 'MISCREG_CCR_ICC', None, 18),
+ 'CcrIccC': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_C', None, 19),
+ 'CcrIccV': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_V', None, 20),
+ 'CcrIccZ': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_Z', None, 21),
+ 'CcrIccN': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_N', None, 22),
+ 'CcrXcc': ('ControlReg', 'udw', 'MISCREG_CCR_XCC', None, 23),
+ 'CcrXccC': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_C', None, 22),
+ 'CcrXccV': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_V', None, 23),
+ 'CcrXccZ': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_Z', None, 24),
+ 'CcrXccN': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_N', None, 25),
+ 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 26),
+ 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 27),
+ #'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 28),
+ 'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 29),
+ 'TickCounter': ('ControlReg', 'udw', 'MISCREG_TICK_COUNTER', None, 32),
+ 'TickNpt': ('ControlReg', 'udw', 'MISCREG_TICK_NPT', None, 33),
+ 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 34),
+ 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 35),
+ 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 36),
+ 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 37),
+ 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 38),
+ 'WstateNormal': ('ControlReg', 'udw', 'MISCREG_WSTATE_NORMAL', None,39),
+ 'WstateOther': ('ControlReg', 'udw', 'MISCREG_WSTATE_OTHER', None, 40),
+ 'Ver': ('ControlReg', 'udw', 'MISCREG_VER', None, 41),
+ 'VerMaxwin': ('ControlReg', 'udw', 'MISCREG_VER_MAXWIN', None, 42),
+ 'VerMaxtl': ('ControlReg', 'udw', 'MISCREG_VER_MAXTL', None, 43),
+ 'VerMask': ('ControlReg', 'udw', 'MISCREG_VER_MASK', None, 44),
+ 'VerImpl': ('ControlReg', 'udw', 'MISCREG_VER_MASK', None, 45),
+ 'VerManuf': ('ControlReg', 'udw', 'MISCREG_VER_MANUF', None, 46),
+ 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 47),
+ 'FsrCexc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC', None, 48),
+ 'FsrCexcNxc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_NXC', None, 49),
+ 'FsrCexcDzc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_DZC', None, 50),
+ 'FsrCexcUfc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_UFC', None, 51),
+ 'FsrCexcOfc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_OFC', None, 52),
+ 'FsrCexcNvc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_NVC', None, 53),
+ 'FsrAexc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC', None, 54),
+ 'FsrAexcNxc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_NXC', None, 55),
+ 'FsrAexcDzc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_DZC', None, 56),
+ 'FsrAexcUfc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_UFC', None, 57),
+ 'FsrAexcOfc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_OFC', None, 58),
+ 'FsrAexcNvc': ('ControlReg', 'udw', 'MISCREC_FSR_AEXC_NVC', None, 59),
+ 'FsrFcc0': ('ControlReg', 'udw', 'MISCREG_FSR_FCC0', None, 60),
+ 'FsrQne': ('ControlReg', 'udw', 'MISCREG_FSR_QNE', None, 61),
+ 'FsrFtt': ('ControlReg', 'udw', 'MISCREG_FSR_FTT', None, 62),
+ 'FsrVer': ('ControlReg', 'udw', 'MISCREG_FSR_VER', None, 63),
+ 'FsrNs': ('ControlReg', 'udw', 'MISCREG_FSR_NS', None, 64),
+ 'FsrTem': ('ControlReg', 'udw', 'MISCREG_FSR_TEM', None, 65),
+ 'FsrTemNxm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_NXM', None, 66),
+ 'FsrTemDzm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_DZM', None, 67),
+ 'FsrTemUfm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_UFM', None, 68),
+ 'FsrTemOfm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_OFM', None, 69),
+ 'FsrTemNvm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_NVM', None, 70),
+ 'FsrRd': ('ControlReg', 'udw', 'MISCREG_FSR_RD', None, 71),
+ 'FsrFcc1': ('ControlReg', 'udw', 'MISCREG_FSR_FCC1', None, 72),
+ 'FsrFcc2': ('ControlReg', 'udw', 'MISCREG_FSR_FCC2', None, 73),
+ 'FsrFcc3': ('ControlReg', 'udw', 'MISCREG_FSR_FCC3', None, 74),
+ 'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 75),
+ 'FprsDl': ('ControlReg', 'udw', 'MISCREG_FPRS_DL', None, 76),
+ 'FprsDu': ('ControlReg', 'udw', 'MISCREG_FPRS_DU', None, 77),
+ 'FprsFef': ('ControlReg', 'udw', 'MISCREG_FPRS_FEF', None, 78)
}};
diff --git a/arch/sparc/isa_traits.hh b/arch/sparc/isa_traits.hh
index bd3c35beb..453d14664 100644
--- a/arch/sparc/isa_traits.hh
+++ b/arch/sparc/isa_traits.hh
@@ -29,46 +29,85 @@
#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 BigEndianGuest {}
+
+#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 SparcISA
{
+
+ // 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 = 96,
+ //XXX These are here solely to get compilation and won't work
+ Fpcr_DepTag = 0,
+ Uniq_DepTag = 0
+ };
+
+ //This makes sure the big endian versions of certain functions are used.
+ using namespace BigEndianGuest;
+
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
- typedef uint8_t RegIndex;
- const int NumFloatRegs = 32;
+ const int NumIntRegs = 32;
+ const int NumFloatRegs = 64;
const int NumMiscRegs = 32;
- const int // Maximum trap level
- const int MaxTL = 4;
- const int
- const int // semantically meaningful register indices
+ // semantically meaningful register indices
const int ZeroReg = 0; // architecturally meaningful
- const int // the rest of these depend on the ABI
+ // 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.
@@ -79,449 +118,70 @@ namespace SparcISA
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
+ // Some OS syscall use a second register (o1) to return a second value
const int SyscallPseudoReturnReg = ArgumentReg1;
+ //XXX These numbers are bogus
+ const int MaxInstSrcRegs = 8;
+ const int MaxInstDestRegs = 9;
+
+ typedef uint64_t IntReg;
+
+ // control register file contents
+ typedef uint64_t MiscReg;
+
+ typedef double FloatReg;
+ typedef uint64_t FloatRegBits;
//8K. This value is implmentation specific; and should probably
//be somewhere else.
const int LogVMPageSize = 13;
const int VMPageSize = (1 << LogVMPageSize);
+ //Why does both the previous set of constants and this one exist?
+ const int PageShift = 13;
+ const int PageBytes = ULL(1) << PageShift;
+ const int BranchPredAddrShiftAmt = 2;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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];
- }
- };
+ const int MachineBytes = 8;
+ const int WordBytes = 4;
+ const int HalfwordBytes = 2;
+ const int ByteBytes = 1;
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);
+ StaticInstPtr decodeInst(ExtMachInst);
// 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);
- }
+#include "arch/sparc/regfile.hh"
- /**
- * Function to insure ISA semantics about 0 registers.
- * @param xc The execution context.
- */
- template <class XC>
+namespace SparcISA
+{
- static inline setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+#if !FULL_SYSTEM
+ static inline void 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();
+ regs->setMiscReg(MISCREG_CCR_XCC_C, 0);
+ regs->setIntReg(ReturnValueReg, return_value.value());
} else {
// got an error, return details
- regs->miscRegFile.ccrFields.iccFields.c = 1;
- regs->intRegFile[ReturnValueReg] = -return_value.value();
+ regs->setMiscReg(MISCREG_CCR_XCC_C, 1);
+ regs->setIntReg(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/linux.cc b/arch/sparc/linux/linux.cc
new file mode 100644
index 000000000..c7ed29358
--- /dev/null
+++ b/arch/sparc/linux/linux.cc
@@ -0,0 +1,68 @@
+/*
+ * 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/linux/linux.hh"
+
+// open(2) flags translation table
+OpenFlagTransTable SparcLinux::openFlagTable[] = {
+#ifdef _MSC_VER
+ { SparcLinux::TGT_O_RDONLY, _O_RDONLY },
+ { SparcLinux::TGT_O_WRONLY, _O_WRONLY },
+ { SparcLinux::TGT_O_RDWR, _O_RDWR },
+ { SparcLinux::TGT_O_APPEND, _O_APPEND },
+ { SparcLinux::TGT_O_CREAT, _O_CREAT },
+ { SparcLinux::TGT_O_TRUNC, _O_TRUNC },
+ { SparcLinux::TGT_O_EXCL, _O_EXCL },
+#ifdef _O_NONBLOCK
+ { SparcLinux::TGT_O_NONBLOCK, _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+ { SparcLinux::TGT_O_NOCTTY, _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+ { SparcLinux::TGT_O_SYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+ { SparcLinux::TGT_O_RDONLY, O_RDONLY },
+ { SparcLinux::TGT_O_WRONLY, O_WRONLY },
+ { SparcLinux::TGT_O_RDWR, O_RDWR },
+ { SparcLinux::TGT_O_APPEND, O_APPEND },
+ { SparcLinux::TGT_O_CREAT, O_CREAT },
+ { SparcLinux::TGT_O_TRUNC, O_TRUNC },
+ { SparcLinux::TGT_O_EXCL, O_EXCL },
+ { SparcLinux::TGT_O_NONBLOCK, O_NONBLOCK },
+ { SparcLinux::TGT_O_NOCTTY, O_NOCTTY },
+#ifdef O_SYNC
+ { SparcLinux::TGT_O_SYNC, O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int SparcLinux::NUM_OPEN_FLAGS =
+ (sizeof(SparcLinux::openFlagTable)/sizeof(SparcLinux::openFlagTable[0]));
+
diff --git a/arch/sparc/linux/linux.hh b/arch/sparc/linux/linux.hh
new file mode 100644
index 000000000..1b31f67b0
--- /dev/null
+++ b/arch/sparc/linux/linux.hh
@@ -0,0 +1,61 @@
+/*
+ * 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_MIPS_LINUX_HH
+#define __MIPS_MIPS_LINUX_HH
+
+#include "kern/linux/linux.hh"
+
+class SparcLinux : public Linux
+{
+ public:
+
+ static OpenFlagTransTable openFlagTable[];
+
+ static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY
+ static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY
+ static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR
+ static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK
+ static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND
+ static const int TGT_O_CREAT = 0x00000200; //!< O_CREAT
+ static const int TGT_O_TRUNC = 0x00000400; //!< O_TRUNC
+ static const int TGT_O_EXCL = 0x00000800; //!< O_EXCL
+ static const int TGT_O_NOCTTY = 0x00008000; //!< O_NOCTTY
+ static const int TGT_O_SYNC = 0x00002000; //!< O_SYNC
+// static const int TGT_O_DRD = 0x00010000; //!< O_DRD
+// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO
+// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE
+// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC
+// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC
+
+ static const int NUM_OPEN_FLAGS;
+
+ static const unsigned TGT_MAP_ANONYMOUS = 0x20;
+};
+
+#endif
diff --git a/arch/sparc/linux/process.cc b/arch/sparc/linux/process.cc
index fa2a7b9f5..71be6a83a 100644
--- a/arch/sparc/linux/process.cc
+++ b/arch/sparc/linux/process.cc
@@ -26,14 +26,13 @@
* 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 "arch/sparc/linux/process.hh"
+#include "arch/sparc/regfile.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"
@@ -55,318 +54,352 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process,
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "sparc");
- name.copyOut(xc->mem);
+ name.copyOut(xc->getMemPort());
+
+ return 0;
+}
+
+
+SyscallReturn SparcISA::getresuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc)
+{
+ const IntReg id = htog(100);
+ Addr ruid = xc->getSyscallArg(0);
+ Addr euid = xc->getSyscallArg(1);
+ Addr suid = xc->getSyscallArg(2);
+ //Handle the EFAULT case
+ //Set the ruid
+ if(ruid)
+ {
+ BufferArg ruidBuff(ruid, sizeof(IntReg));
+ memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg));
+ ruidBuff.copyOut(xc->getMemPort());
+ }
+ //Set the euid
+ if(euid)
+ {
+ BufferArg euidBuff(euid, sizeof(IntReg));
+ memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg));
+ euidBuff.copyOut(xc->getMemPort());
+ }
+ //Set the suid
+ if(suid)
+ {
+ BufferArg suidBuff(suid, sizeof(IntReg));
+ memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg));
+ suidBuff.copyOut(xc->getMemPort());
+ }
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);
+ /* 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<SparcLinux>),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 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", fstatFunc<SparcLinux>),
+ /* 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", mmapFunc<SparcLinux>),
+ /* 72 */ SyscallDesc("setreuid32", unimplementedFunc),
+ /* 73 */ SyscallDesc("munmap", munmapFunc),
+ /* 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", getresuidFunc),
+ /* 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", exitFunc),
+ /* 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", unimplementedFunc),
+ /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
+ /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
+ /* 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,
+ System * system,
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),
+ : SparcLiveProcess(name, objFile, system,
+ 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
+ // The sparc syscall table must be <= 284 entries because that is all there
// is space for.
- assert(Num_Syscall_Descs <= 283);
-
- init_regs->intRegFile[0] = 0;
+ assert(Num_Syscall_Descs <= 284);
}
SyscallDesc*
-AlphaLinuxProcess::getDesc(int callnum)
+SparcLinuxProcess::getDesc(int callnum)
{
if (callnum < 0 || callnum > Num_Syscall_Descs)
return NULL;
diff --git a/arch/sparc/linux/process.hh b/arch/sparc/linux/process.hh
index c41406b4b..23ce66d02 100644
--- a/arch/sparc/linux/process.hh
+++ b/arch/sparc/linux/process.hh
@@ -29,16 +29,20 @@
#ifndef __SPARC_LINUX_PROCESS_HH__
#define __SPARC_LINUX_PROCESS_HH__
+#include "arch/sparc/linux/linux.hh"
+#include "arch/sparc/process.hh"
#include "sim/process.hh"
+namespace SparcISA {
/// A process with emulated SPARC/Linux syscalls.
-class SparcLinuxProcess : public LiveProcess
+class SparcLinuxProcess : public SparcLiveProcess
{
public:
/// Constructor.
SparcLinuxProcess(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);
@@ -54,5 +58,8 @@ class SparcLinuxProcess : public LiveProcess
const int Num_Syscall_Descs;
};
+SyscallReturn getresuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+} // namespace SparcISA
#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/arch/sparc/process.cc b/arch/sparc/process.cc
index 53a215379..7f2b0d40a 100644
--- a/arch/sparc/process.cc
+++ b/arch/sparc/process.cc
@@ -26,22 +26,38 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
+#include "arch/sparc/linux/process.hh"
+#include "base/loader/object_file.hh"
+#include "base/misc.hh"
+#include "cpu/exec_context.hh"
+#include "mem/page_table.hh"
+#include "mem/translating_port.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
-namespace SparcISA
-{
+using namespace std;
+using namespace SparcISA;
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
+SparcLiveProcess *
+SparcLiveProcess::create(const std::string &nm, System *system, int stdin_fd,
+ int stdout_fd, int stderr_fd, std::string executable,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
{
- LiveProcess * process = NULL;
+ SparcLiveProcess *process = NULL;
+
+ ObjectFile *objFile = createObjectFile(executable);
+ if (objFile == NULL) {
+ fatal("Can't load object file %s", executable);
+ }
+
+
if (objFile->getArch() != ObjectFile::SPARC)
- fatal("Object file does not match architecture.");
+ fatal("Object file with arch %x does not match architecture %x.", objFile->getArch(), ObjectFile::SPARC);
switch (objFile->getOpSys()) {
case ObjectFile::Linux:
- process = new SparcLinuxProcess(nm, objFile,
+ process = new SparcLinuxProcess(nm, objFile, system,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
break;
@@ -50,7 +66,316 @@ createProcess(const string &nm, ObjectFile * objFile,
default:
fatal("Unknown/unsupported operating system.");
}
+
+ if (process == NULL)
+ fatal("Unknown error creating process object.");
return process;
}
-} // namespace SparcISA
+SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
+ : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
+ argv, envp)
+{
+
+ // XXX all the below need to be updated for SPARC - Ali
+ brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
+ brk_point = roundUp(brk_point, VMPageSize);
+
+ // Set up stack. On SPARC Linux, stack goes from the top of memory
+ // downward, less the hole for the kernel address space.
+ stack_base = ((Addr)0x80000000000ULL);
+
+ // Set up region for mmaps. Tru64 seems to start just above 0 and
+ // grow up from there.
+ mmap_start = mmap_end = 0x800000;
+
+ // Set pointer for next thread stack. Reserve 8M for main stack.
+ next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+}
+
+void
+SparcLiveProcess::startup()
+{
+ argsInit(MachineBytes, VMPageSize);
+
+ //From the SPARC ABI
+
+ //The process runs in user mode
+ execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_PRIV, 0);
+ //Interrupts are enabled
+ execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_IE, 1);
+ //Round to nearest
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_RD, 0);
+ //Floating point traps are not enabled
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_TEM, 0);
+ //Turn non standard mode off
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_NS, 0);
+ //The floating point queue is empty
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_QNE, 0);
+ //There are no accrued eexecContext[0]eptions
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_AEXC, 0);
+ //There are no current eexecContext[0]eptions
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_CEXC, 0);
+
+ /*
+ * Register window management registers
+ */
+
+ //No windows contain info from other programs
+ execContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
+ //There are no windows to pop
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
+ //All windows are available to save into
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
+ //All windows are "clean"
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
+ //Start with register window 0
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
+}
+
+m5_auxv_t buildAuxVect(int64_t type, int64_t val)
+{
+ m5_auxv_t result;
+ result.a_type = TheISA::htog(type);
+ result.a_val = TheISA::htog(val);
+ return result;
+}
+
+void
+SparcLiveProcess::argsInit(int intSize, int pageSize)
+{
+ Process::startup();
+
+ Addr alignmentMask = ~(intSize - 1);
+
+ // load object file into target memory
+ objFile->loadSections(initVirtMem);
+
+ //These are the auxilliary vector types
+ enum auxTypes
+ {
+ SPARC_AT_HWCAP = 16,
+ SPARC_AT_PAGESZ = 6,
+ SPARC_AT_CLKTCK = 17,
+ SPARC_AT_PHDR = 3,
+ SPARC_AT_PHENT = 4,
+ SPARC_AT_PHNUM = 5,
+ SPARC_AT_BASE = 7,
+ SPARC_AT_FLAGS = 8,
+ SPARC_AT_ENTRY = 9,
+ SPARC_AT_UID = 11,
+ SPARC_AT_EUID = 12,
+ SPARC_AT_GID = 13,
+ SPARC_AT_EGID = 14
+ };
+
+ enum hardwareCaps
+ {
+ M5_HWCAP_SPARC_FLUSH = 1,
+ M5_HWCAP_SPARC_STBAR = 2,
+ M5_HWCAP_SPARC_SWAP = 4,
+ M5_HWCAP_SPARC_MULDIV = 8,
+ M5_HWCAP_SPARC_V9 = 16,
+ //This one should technically only be set
+ //if there is a cheetah or cheetah_plus tlb,
+ //but we'll use it all the time
+ M5_HWCAP_SPARC_ULTRA3 = 32
+ };
+
+ const int64_t hwcap =
+ M5_HWCAP_SPARC_FLUSH |
+ M5_HWCAP_SPARC_STBAR |
+ M5_HWCAP_SPARC_SWAP |
+ M5_HWCAP_SPARC_MULDIV |
+ M5_HWCAP_SPARC_V9 |
+ M5_HWCAP_SPARC_ULTRA3;
+
+ //Setup the auxilliary vectors. These will already have
+ //endian conversion.
+ auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100));
+ auxv.push_back(buildAuxVect(SPARC_AT_GID, 100));
+ auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100));
+ auxv.push_back(buildAuxVect(SPARC_AT_UID, 100));
+ //This would work, but the entry point is a protected member
+ //auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entry));
+ auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0));
+ //This is the address of the elf "interpreter", which I don't
+ //think we currently set up. It should be set to 0 (I think)
+ //auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0));
+ //This is the number of headers which were in the original elf
+ //file. This information isn't avaibale by this point.
+ //auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, 3));
+ //This is the size of a program header entry. This isn't easy
+ //to compute here.
+ //auxv.push_back(buildAuxVect(SPARC_AT_PHENT, blah));
+ //This is should be set to load_addr (whatever that is) +
+ //e_phoff. I think it's a pointer to the program headers.
+ //auxv.push_back(buildAuxVect(SPARC_AT_PHDR, blah));
+ //This should be easy to get right, but I won't set it for now
+ //auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, blah));
+ auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
+ auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap));
+
+ //Figure out how big the initial stack needs to be
+
+ //Each auxilliary vector is two 8 byte words
+ int aux_data_size = 2 * intSize * auxv.size();
+ int env_data_size = 0;
+ for (int i = 0; i < envp.size(); ++i) {
+ env_data_size += envp[i].size() + 1;
+ }
+ int arg_data_size = 0;
+ for (int i = 0; i < argv.size(); ++i) {
+ arg_data_size += argv[i].size() + 1;
+ }
+
+ int aux_array_size = intSize * 2 * (auxv.size() + 1);
+
+ int argv_array_size = intSize * (argv.size() + 1);
+ int envp_array_size = intSize * (envp.size() + 1);
+
+ int argc_size = intSize;
+ int window_save_size = intSize * 16;
+
+ int info_block_size =
+ (aux_data_size +
+ env_data_size +
+ arg_data_size +
+ ~alignmentMask) & alignmentMask;
+
+ int info_block_padding =
+ info_block_size -
+ aux_data_size -
+ env_data_size -
+ arg_data_size;
+
+ int space_needed =
+ info_block_size +
+ aux_array_size +
+ envp_array_size +
+ argv_array_size +
+ argc_size +
+ window_save_size;
+
+ stack_min = stack_base - space_needed;
+ stack_min &= alignmentMask;
+ stack_size = stack_base - stack_min;
+
+ // map memory
+ pTable->allocate(roundDown(stack_min, pageSize),
+ roundUp(stack_size, pageSize));
+
+ // map out initial stack contents
+ Addr aux_data_base = stack_base - aux_data_size - info_block_padding;
+ Addr env_data_base = aux_data_base - env_data_size;
+ Addr arg_data_base = env_data_base - arg_data_size;
+ Addr auxv_array_base = arg_data_base - aux_array_size;
+ Addr envp_array_base = auxv_array_base - envp_array_size;
+ Addr argv_array_base = envp_array_base - argv_array_size;
+ Addr argc_base = argv_array_base - argc_size;
+ Addr window_save_base = argc_base - window_save_size;
+
+ DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
+ DPRINTF(Sparc, "0x%x - aux data\n", aux_data_base);
+ DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
+ DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
+ DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
+ DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
+ DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
+ DPRINTF(Sparc, "0x%x - argc \n", argc_base);
+ DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
+ DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
+
+ // write contents to stack
+ uint64_t argc = argv.size();
+ uint64_t guestArgc = TheISA::htog(argc);
+
+ //Copy the aux stuff
+ for(int x = 0; x < auxv.size(); x++)
+ {
+ initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
+ (uint8_t*)&(auxv[x].a_type), intSize);
+ initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
+ (uint8_t*)&(auxv[x].a_val), intSize);
+ }
+ //Write out the terminating zeroed auxilliary vector
+ const uint64_t zero = 0;
+ initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
+ (uint8_t*)&zero, 2 * intSize);
+
+ copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
+ copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
+
+ initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
+
+ execContexts[0]->setIntReg(ArgumentReg0, argc);
+ execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
+ execContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
+
+ Addr prog_entry = objFile->entryPoint();
+ execContexts[0]->setPC(prog_entry);
+ execContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+ execContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+
+// num_processes++;
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess)
+
+ VectorParam<string> cmd;
+ Param<string> executable;
+ Param<string> input;
+ Param<string> output;
+ VectorParam<string> env;
+ SimObjectParam<System *> system;
+
+END_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess)
+
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(SparcLiveProcess)
+
+ INIT_PARAM(cmd, "command line (executable plus arguments)"),
+ INIT_PARAM(executable, "executable (overrides cmd[0] if set)"),
+ INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
+ INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
+ INIT_PARAM(env, "environment settings"),
+ INIT_PARAM(system, "system")
+
+END_INIT_SIM_OBJECT_PARAMS(SparcLiveProcess)
+
+
+CREATE_SIM_OBJECT(SparcLiveProcess)
+{
+ string in = input;
+ string out = output;
+
+ // initialize file descriptors to default: same as simulator
+ int stdin_fd, stdout_fd, stderr_fd;
+
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else
+ stdin_fd = Process::openInputFile(input);
+
+ if (out == "stdout" || out == "cout")
+ stdout_fd = STDOUT_FILENO;
+ else if (out == "stderr" || out == "cerr")
+ stdout_fd = STDERR_FILENO;
+ else
+ stdout_fd = Process::openOutputFile(out);
+
+ stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+
+ return SparcLiveProcess::create(getInstanceName(), system,
+ stdin_fd, stdout_fd, stderr_fd,
+ (string)executable == "" ? cmd[0] : executable,
+ cmd, env);
+}
+
+
+REGISTER_SIM_OBJECT("SparcLiveProcess", SparcLiveProcess)
+
+
diff --git a/arch/sparc/process.hh b/arch/sparc/process.hh
index 48041a316..c177f20a5 100644
--- a/arch/sparc/process.hh
+++ b/arch/sparc/process.hh
@@ -29,17 +29,51 @@
#ifndef __SPARC_PROCESS_HH__
#define __SPARC_PROCESS_HH__
-#include "arch/sparc/linux/process.hh"
-#include "base/loader/object_file.hh"
+#include <string>
+#include <vector>
+#include "sim/process.hh"
-namespace SparcISA
+class ObjectFile;
+class System;
+
+typedef struct
+{
+ int64_t a_type;
+ union {
+ int64_t a_val;
+ Addr a_ptr;
+ Addr a_fcn;
+ };
+} m5_auxv_t;
+
+class SparcLiveProcess : public LiveProcess
{
+ protected:
+
+ static const Addr StackBias = 2047;
+
+ std::vector<m5_auxv_t> auxv;
+
+ SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
+
+ void startup();
+
+ public:
+ // this function is used to create the LiveProcess object, since
+ // we can't tell which subclass of LiveProcess to use until we
+ // open and look at the object file.
+ static SparcLiveProcess *create(const std::string &nm,
+ System *_system,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::string executable,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp);
+ void argsInit(int intSize, int pageSize);
-} // namespace SparcISA
+};
#endif // __SPARC_PROCESS_HH__
diff --git a/arch/sparc/regfile.hh b/arch/sparc/regfile.hh
new file mode 100644
index 000000000..5169a332f
--- /dev/null
+++ b/arch/sparc/regfile.hh
@@ -0,0 +1,812 @@
+/*
+ * 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_REGFILE_HH__
+#define __ARCH_SPARC_REGFILE_HH__
+
+#include "arch/sparc/faults.hh"
+#include "base/trace.hh"
+#include "sim/byteswap.hh"
+#include "sim/host.hh"
+
+class Checkpoint;
+
+namespace SparcISA
+{
+
+ typedef uint8_t RegIndex;
+
+ // MAXTL - maximum trap level
+ const int MaxTL = 4;
+
+ // NWINDOWS - number of register windows, can be 3 to 32
+ const int NWindows = 32;
+
+ class IntRegFile
+ {
+ protected:
+ static const int FrameOffsetBits = 3;
+ static const int FrameNumBits = 2;
+
+ static const int RegsPerFrame = 1 << FrameOffsetBits;
+ static const int FrameNumMask =
+ (FrameNumBits == sizeof(int)) ?
+ (unsigned int)(-1) :
+ (1 << FrameNumBits) - 1;
+ static const int FrameOffsetMask =
+ (FrameOffsetBits == sizeof(int)) ?
+ (unsigned int)(-1) :
+ (1 << FrameOffsetBits) - 1;
+
+ IntReg regGlobals[RegsPerFrame];
+ IntReg altGlobals[RegsPerFrame];
+ IntReg regSegments[2 * NWindows][RegsPerFrame];
+
+ enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
+
+ IntReg * regView[NumFrames];
+
+ static const int RegGlobalOffset = 0;
+ static const int AltGlobalOffset = 8;
+ static const int FrameOffset = 16;
+ int offset[NumFrames];
+
+ public:
+
+ int flattenIndex(int reg)
+ {
+ int flatIndex = offset[reg >> FrameOffsetBits]
+ | (reg & FrameOffsetMask);
+ DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex);
+ return flatIndex;
+ }
+
+ void clear()
+ {
+ bzero(regGlobals, sizeof(regGlobals));
+ bzero(altGlobals, sizeof(altGlobals));
+ for(int x = 0; x < 2 * NWindows; x++)
+ bzero(regSegments[x], sizeof(regSegments[x]));
+ }
+
+ IntRegFile()
+ {
+ offset[Globals] = 0;
+ regView[Globals] = regGlobals;
+ setCWP(0);
+ clear();
+ }
+
+ IntReg readReg(int intReg)
+ {
+ IntReg val =
+ regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
+ DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
+ return val;
+ }
+
+ Fault setReg(int intReg, const IntReg &val)
+ {
+ if(intReg)
+ DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
+ regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
+ return NoFault;
+ }
+
+ //This doesn't effect the actual CWP register.
+ //It's purpose is to adjust the view of the register file
+ //to what it would be if CWP = cwp.
+ void setCWP(int cwp)
+ {
+ int index = ((NWindows - cwp) % NWindows) * 2;
+ offset[Outputs] = FrameOffset + (index * RegsPerFrame);
+ offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame);
+ offset[Inputs] = FrameOffset +
+ (((index+2) % (NWindows * 2)) * RegsPerFrame);
+ regView[Outputs] = regSegments[index];
+ regView[Locals] = regSegments[index+1];
+ regView[Inputs] = regSegments[(index+2) % (NWindows * 2)];
+
+ DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp);
+ }
+
+ void setAltGlobals(bool useAlt)
+ {
+ DPRINTF(Sparc, "Now using %s globals",
+ useAlt ? "alternate" : "regular");
+ regView[Globals] = useAlt ? altGlobals : regGlobals;
+
+ // You have not included an out-of-class definition of your static
+ // members. See [9.4.2]/4 and about a billion gcc bug reports. If
+ // statements get around the problem through some magic, and than
+ // seems nicer that putting a definition of them in a c file
+ // somewhere.
+ if (useAlt)
+ offset[Globals] = AltGlobalOffset;
+ else
+ offset[Globals] = RegGlobalOffset;
+ }
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ typedef float float32_t;
+ typedef double float64_t;
+ //FIXME long double refers to a 10 byte float, rather than a
+ //16 byte float as required. This data type may have to be emulated.
+ typedef double float128_t;
+
+ class FloatRegFile
+ {
+ public:
+ static const int SingleWidth = 32;
+ static const int DoubleWidth = 64;
+ static const int QuadWidth = 128;
+
+ protected:
+
+ //Since the floating point registers overlap each other,
+ //A generic storage space is used. The float to be returned is
+ //pulled from the appropriate section of this region.
+ char regSpace[SingleWidth / 8 * NumFloatRegs];
+
+ public:
+
+ void clear()
+ {
+ bzero(regSpace, sizeof(regSpace));
+ }
+
+ FloatReg readReg(int floatReg, int width)
+ {
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ switch(width)
+ {
+ case SingleWidth:
+ float32_t result32;
+ memcpy(&result32, regSpace + 4 * floatReg, width);
+ return htog(result32);
+ case DoubleWidth:
+ float64_t result64;
+ memcpy(&result64, regSpace + 4 * floatReg, width);
+ return htog(result64);
+ case QuadWidth:
+ float128_t result128;
+ memcpy(&result128, regSpace + 4 * floatReg, width);
+ return htog(result128);
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ }
+
+ FloatRegBits readRegBits(int floatReg, int width)
+ {
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ switch(width)
+ {
+ case SingleWidth:
+ uint32_t result32;
+ memcpy(&result32, regSpace + 4 * floatReg, width);
+ return htog(result32);
+ case DoubleWidth:
+ uint64_t result64;
+ memcpy(&result64, regSpace + 4 * floatReg, width);
+ return htog(result64);
+ case QuadWidth:
+ uint64_t result128;
+ memcpy(&result128, regSpace + 4 * floatReg, width);
+ return htog(result128);
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ }
+
+ Fault setReg(int floatReg, const FloatReg &val, int width)
+ {
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ switch(width)
+ {
+ case SingleWidth:
+ uint32_t result32 = gtoh((uint32_t)val);
+ memcpy(regSpace + 4 * floatReg, &result32, width);
+ case DoubleWidth:
+ uint64_t result64 = gtoh((uint64_t)val);
+ memcpy(regSpace + 4 * floatReg, &result64, width);
+ case QuadWidth:
+ uint64_t result128 = gtoh((uint64_t)val);
+ memcpy(regSpace + 4 * floatReg, &result128, width);
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ return NoFault;
+ }
+
+ Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
+ {
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ switch(width)
+ {
+ case SingleWidth:
+ uint32_t result32 = gtoh((uint32_t)val);
+ memcpy(regSpace + 4 * floatReg, &result32, width);
+ case DoubleWidth:
+ uint64_t result64 = gtoh((uint64_t)val);
+ memcpy(regSpace + 4 * floatReg, &result64, width);
+ case QuadWidth:
+ uint64_t result128 = gtoh((uint64_t)val);
+ memcpy(regSpace + 4 * floatReg, &result128, width);
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ return NoFault;
+ }
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ enum MiscRegIndex
+ {
+ MISCREG_PSTATE,
+ MISCREG_PSTATE_AG,
+ MISCREG_PSTATE_IE,
+ MISCREG_PSTATE_PRIV,
+ MISCREG_PSTATE_AM,
+ MISCREG_PSTATE_PEF,
+ MISCREG_PSTATE_RED,
+ MISCREG_PSTATE_MM,
+ MISCREG_PSTATE_TLE,
+ MISCREG_PSTATE_CLE,
+ MISCREG_TBA,
+ MISCREG_Y,
+ MISCREG_Y_VALUE,
+ MISCREG_PIL,
+ MISCREG_CWP,
+ MISCREG_TT_BASE,
+ MISCREG_TT_END = MISCREG_TT_BASE + MaxTL,
+ MISCREG_CCR,
+ MISCREG_CCR_ICC,
+ MISCREG_CCR_ICC_C,
+ MISCREG_CCR_ICC_V,
+ MISCREG_CCR_ICC_Z,
+ MISCREG_CCR_ICC_N,
+ MISCREG_CCR_XCC,
+ MISCREG_CCR_XCC_C,
+ MISCREG_CCR_XCC_V,
+ MISCREG_CCR_XCC_Z,
+ MISCREG_CCR_XCC_N,
+ MISCREG_ASI,
+ MISCREG_TL,
+ MISCREG_TPC_BASE,
+ MISCREG_TPC_END = MISCREG_TPC_BASE + MaxTL,
+ MISCREG_TNPC_BASE,
+ MISCREG_TNPC_END = MISCREG_TNPC_BASE + MaxTL,
+ MISCREG_TSTATE_BASE,
+ MISCREG_TSTATE_END = MISCREG_TSTATE_BASE + MaxTL,
+ MISCREG_TSTATE_CWP_BASE,
+ MISCREG_TSTATE_CWP_END = MISCREG_TSTATE_CWP_BASE + MaxTL,
+ MISCREG_TSTATE_PSTATE_BASE,
+ MISCREG_TSTATE_PSTATE_END = MISCREG_TSTATE_PSTATE_BASE + MaxTL,
+ MISCREG_TSTATE_ASI_BASE,
+ MISCREG_TSTATE_ASI_END = MISCREG_TSTATE_ASI_BASE + MaxTL,
+ MISCREG_TSTATE_CCR_BASE,
+ MISCREG_TSTATE_CCR_END = MISCREG_TSTATE_CCR_BASE + MaxTL,
+ MISCREG_TICK,
+ MISCREG_TICK_COUNTER,
+ MISCREG_TICK_NPT,
+ MISCREG_CANSAVE,
+ MISCREG_CANRESTORE,
+ MISCREG_OTHERWIN,
+ MISCREG_CLEANWIN,
+ MISCREG_WSTATE,
+ MISCREG_WSTATE_NORMAL,
+ MISCREG_WSTATE_OTHER,
+ MISCREG_VER,
+ MISCREG_VER_MAXWIN,
+ MISCREG_VER_MAXTL,
+ MISCREG_VER_MASK,
+ MISCREG_VER_IMPL,
+ MISCREG_VER_MANUF,
+ MISCREG_FSR,
+ MISCREG_FSR_CEXC,
+ MISCREG_FSR_CEXC_NXC,
+ MISCREG_FSR_CEXC_DZC,
+ MISCREG_FSR_CEXC_UFC,
+ MISCREG_FSR_CEXC_OFC,
+ MISCREG_FSR_CEXC_NVC,
+ MISCREG_FSR_AEXC,
+ MISCREG_FSR_AEXC_NXC,
+ MISCREG_FSR_AEXC_DZC,
+ MISCREG_FSR_AEXC_UFC,
+ MISCREG_FSR_AEXC_OFC,
+ MISCREG_FSR_AEXC_NVC,
+ MISCREG_FSR_FCC0,
+ MISCREG_FSR_QNE,
+ MISCREG_FSR_FTT,
+ MISCREG_FSR_VER,
+ MISCREG_FSR_NS,
+ MISCREG_FSR_TEM,
+ MISCREG_FSR_TEM_NXM,
+ MISCREG_FSR_TEM_DZM,
+ MISCREG_FSR_TEM_UFM,
+ MISCREG_FSR_TEM_OFM,
+ MISCREG_FSR_TEM_NVM,
+ MISCREG_FSR_RD,
+ MISCREG_FSR_FCC1,
+ MISCREG_FSR_FCC2,
+ MISCREG_FSR_FCC3,
+ MISCREG_FPRS,
+ MISCREG_FPRS_DL,
+ MISCREG_FPRS_DU,
+ MISCREG_FPRS_FEF,
+ numMiscRegs
+ };
+
+ // 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
+ } cexcFields;
+ };
+ 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
+ } aexcFields;
+ };
+ 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:
+
+ void reset()
+ {
+ pstateFields.pef = 0; //No FPU
+ //pstateFields.pef = 1; //FPU
+#if FULL_SYSTEM
+ //For SPARC, when a system is first started, there is a power
+ //on reset Trap which sets the processor into the following state.
+ //Bits that aren't set aren't defined on startup.
+ tl = MaxTL;
+ tt[tl] = PowerOnReset.trapType();
+ pstateFields.mm = 0; //Total Store Order
+ pstateFields.red = 1; //Enter RED_State
+ pstateFields.am = 0; //Address Masking is turned off
+ pstateFields.priv = 1; //Processor enters privileged mode
+ pstateFields.ie = 0; //Interrupts are disabled
+ pstateFields.ag = 1; //Globals are replaced with alternate globals
+ pstateFields.tle = 0; //Big Endian mode for traps
+ pstateFields.cle = 0; //Big Endian mode for non-traps
+ tickFields.npt = 1; //The TICK register is unreadable by
+ //non-priveleged software
+#else
+/* //This sets up the initial state of the processor for usermode processes
+ pstateFields.priv = 0; //Process runs in user mode
+ pstateFields.ie = 1; //Interrupts are enabled
+ fsrFields.rd = 0; //Round to nearest
+ fsrFields.tem = 0; //Floating point traps not enabled
+ fsrFields.ns = 0; //Non standard mode off
+ fsrFields.qne = 0; //Floating point queue is empty
+ fsrFields.aexc = 0; //No accrued exceptions
+ fsrFields.cexc = 0; //No current exceptions
+
+ //Register window management registers
+ otherwin = 0; //No windows contain info from other programs
+ canrestore = 0; //There are no windows to pop
+ cansave = MaxTL - 2; //All windows are available to save into
+ cleanwin = MaxTL;*/
+#endif
+ }
+
+ MiscRegFile()
+ {
+ reset();
+ }
+
+ MiscReg readReg(int miscReg);
+
+ MiscReg readRegWithEffect(int miscReg, Fault &fault, ExecContext *xc);
+
+ Fault setReg(int miscReg, const MiscReg &val);
+
+ Fault setRegWithEffect(int miscReg,
+ const MiscReg &val, ExecContext * xc);
+
+ void serialize(std::ostream & os);
+
+ void unserialize(Checkpoint * cp, const std::string & section);
+
+ void copyMiscRegs(ExecContext * xc);
+ };
+
+ typedef union
+ {
+ IntReg intreg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ class RegFile
+ {
+ protected:
+ Addr pc; // Program Counter
+ Addr npc; // Next Program Counter
+ Addr nnpc;
+
+ public:
+ Addr readPC()
+ {
+ return pc;
+ }
+
+ void setPC(Addr val)
+ {
+ pc = val;
+ }
+
+ Addr readNextPC()
+ {
+ return npc;
+ }
+
+ void setNextPC(Addr val)
+ {
+ npc = val;
+ }
+
+ Addr readNextNPC()
+ {
+ return nnpc;
+ }
+
+ void setNextNPC(Addr val)
+ {
+ nnpc = val;
+ }
+
+ protected:
+ IntRegFile intRegFile; // integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegFile; // control register file
+
+ public:
+
+ void clear()
+ {
+ intRegFile.clear();
+ floatRegFile.clear();
+ }
+
+ int flattenIntIndex(int reg)
+ {
+ return intRegFile.flattenIndex(reg);
+ }
+
+ MiscReg readMiscReg(int miscReg)
+ {
+ return miscRegFile.readReg(miscReg);
+ }
+
+ MiscReg readMiscRegWithEffect(int miscReg,
+ Fault &fault, ExecContext *xc)
+ {
+ return miscRegFile.readRegWithEffect(miscReg, fault, xc);
+ }
+
+ Fault setMiscReg(int miscReg, const MiscReg &val)
+ {
+ return miscRegFile.setReg(miscReg, val);
+ }
+
+ Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
+ ExecContext * xc)
+ {
+ return miscRegFile.setRegWithEffect(miscReg, val, xc);
+ }
+
+ FloatReg readFloatReg(int floatReg, int width)
+ {
+ return floatRegFile.readReg(floatReg, width);
+ }
+
+ FloatReg readFloatReg(int floatReg)
+ {
+ //Use the "natural" width of a single float
+ return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth);
+ }
+
+ FloatRegBits readFloatRegBits(int floatReg, int width)
+ {
+ return floatRegFile.readRegBits(floatReg, width);
+ }
+
+ FloatRegBits readFloatRegBits(int floatReg)
+ {
+ //Use the "natural" width of a single float
+ return floatRegFile.readRegBits(floatReg,
+ FloatRegFile::SingleWidth);
+ }
+
+ Fault setFloatReg(int floatReg, const FloatReg &val, int width)
+ {
+ return floatRegFile.setReg(floatReg, val, width);
+ }
+
+ Fault setFloatReg(int floatReg, const FloatReg &val)
+ {
+ //Use the "natural" width of a single float
+ return setFloatReg(floatReg, val, FloatRegFile::SingleWidth);
+ }
+
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
+ {
+ return floatRegFile.setRegBits(floatReg, val, width);
+ }
+
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
+ {
+ //Use the "natural" width of a single float
+ return floatRegFile.setRegBits(floatReg, val,
+ FloatRegFile::SingleWidth);
+ }
+
+ IntReg readIntReg(int intReg)
+ {
+ return intRegFile.readReg(intReg);
+ }
+
+ Fault setIntReg(int intReg, const IntReg &val)
+ {
+ return intRegFile.setReg(intReg, val);
+ }
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ public:
+
+ enum ContextParam
+ {
+ CONTEXT_CWP,
+ CONTEXT_GLOBALS
+ };
+
+ union ContextVal
+ {
+ MiscReg reg;
+ bool altGlobals;
+ };
+
+ void changeContext(ContextParam param, ContextVal val)
+ {
+ switch(param)
+ {
+ case CONTEXT_CWP:
+ intRegFile.setCWP(val.reg);
+ break;
+ case CONTEXT_GLOBALS:
+ intRegFile.setAltGlobals(val.altGlobals);
+ break;
+ default:
+ panic("Tried to set illegal context parameter in the SPARC regfile.\n");
+ }
+ }
+ };
+
+ void copyRegs(ExecContext *src, ExecContext *dest);
+
+ void copyMiscRegs(ExecContext *src, ExecContext *dest);
+
+} // namespace SparcISA
+
+#endif
diff --git a/arch/sparc/system.cc b/arch/sparc/system.cc
new file mode 100644
index 000000000..1e2882607
--- /dev/null
+++ b/arch/sparc/system.cc
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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/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/physical.hh"
+#include "sim/byteswap.hh"
+#include "sim/builder.hh"
+
+
+using namespace BigEndianGuest;
+
+SparcSystem::SparcSystem(Params *p)
+ : System(p)
+{
+ resetSymtab = new SymbolTable;
+ hypervisorSymtab = new SymbolTable;
+ openbootSymtab = new SymbolTable;
+
+
+ /**
+ * Load the boot code, and hypervisor into memory.
+ */
+ // Read the reset binary
+ reset = createObjectFile(params()->reset_bin);
+ if (reset == NULL)
+ fatal("Could not load reset binary %s", params()->reset_bin);
+
+ // Read the openboot binary
+ openboot = createObjectFile(params()->openboot_bin);
+ if (openboot == NULL)
+ fatal("Could not load openboot bianry %s", params()->openboot_bin);
+
+ // Read the hypervisor binary
+ hypervisor = createObjectFile(params()->hypervisor_bin);
+ if (hypervisor == NULL)
+ fatal("Could not load hypervisor binary %s", params()->hypervisor_bin);
+
+
+ // Load reset binary into memory
+ reset->loadSections(&functionalPort, SparcISA::LoadAddrMask);
+ // Load the openboot binary
+ openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask);
+ // Load the hypervisor binary
+ hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask);
+
+ // load symbols
+ if (!reset->loadGlobalSymbols(reset))
+ panic("could not load reset symbols\n");
+
+ if (!openboot->loadGlobalSymbols(openbootSymtab))
+ panic("could not load openboot symbols\n");
+
+ if (!hypervisor->loadLocalSymbols(hypervisorSymtab))
+ panic("could not load hypervisor symbols\n");
+
+ // load symbols into debug table
+ if (!reset->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load reset symbols\n");
+
+ if (!openboot->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load openboot symbols\n");
+
+ if (!hypervisor->loadLocalSymbols(debugSymbolTable))
+ panic("could not load hypervisor symbols\n");
+
+
+ // @todo any fixup code over writing data in binaries on setting break
+ // events on functions should happen here.
+
+}
+
+SparcSystem::~SparcSystem()
+{
+ delete resetSymtab;
+ delete hypervisorSymtab;
+ delete openbootSymtab;
+ delete reset;
+ delete openboot;
+ delete hypervisor;
+}
+
+bool
+SparcSystem::breakpoint()
+{
+ panic("Need to implement");
+}
+
+void
+SparcSystem::serialize(std::ostream &os)
+{
+ System::serialize(os);
+ resetSymtab->serialize("reset_symtab", os);
+ hypervisorSymtab->serialize("hypervisor_symtab", os);
+ openbootSymtab->serialize("openboot_symtab", os);
+}
+
+
+void
+SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
+{
+ System::unserialize(cp,section);
+ resetSymtab->unserialize("reset_symtab", cp, section);
+ hypervisorSymtab->unserialize("hypervisor_symtab", cp, section);
+ openbootSymtab->unserialize("openboot_symtab", cp, section);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
+
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<std::string> kernel;
+ Param<std::string> reset_bin;
+ Param<std::string> hypervisor_bin;
+ Param<std::string> openboot_bin;
+
+ Param<std::string> boot_osflags;
+ Param<std::string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<bool> bin;
+ VectorParam<std::string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(reset_bin, "file that contains the reset code"),
+ INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
+ INIT_PARAM(openboot_bin, "file that contains the openboot code"),
+ 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(SparcSystem)
+
+CREATE_SIM_OBJECT(SparcSystem)
+{
+ SparcSystem::Params *p = new SparcSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->reset_bin = reset_bin;
+ p->hypervisor_bin = hypervisor_bin;
+ p->openboot_bin = openboot_bin;
+ 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 SparcSystem(p);
+}
+
+REGISTER_SIM_OBJECT("SparcSystem", SparcSystem)
+
+
diff --git a/arch/sparc/system.hh b/arch/sparc/system.hh
new file mode 100644
index 000000000..27aa8768a
--- /dev/null
+++ b/arch/sparc/system.hh
@@ -0,0 +1,114 @@
+/*
+ * 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_SPARC_SYSTEM_HH__
+#define __ARCH_SPARC_SYSTEM_HH__
+
+#include <string>
+#include <vector>
+
+#include "base/loader/symtab.hh"
+#include "cpu/pc_event.hh"
+#include "kern/system_events.hh"
+#include "sim/sim_object.hh"
+#include "sim/system.hh"
+
+class SparcSystem : public System
+{
+ public:
+ struct Params : public System::Params
+ {
+ std::string reset_bin;
+ std::string hypervison_bin;
+ std::string openboot_bin;
+ std::string boot_osflags;
+ uint64_t system_type;
+ uint64_t system_rev;
+ };
+
+ SparcSystem(Params *p);
+
+ ~SparcaSystem();
+
+ virtual bool breakpoint();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ /** reset binary symbol table */
+ SymbolTable *resetSymtab;
+
+ /** hypervison binary symbol table */
+ SymbolTable *hypervisorSymtab;
+
+ /** openboot symbol table */
+ SymbolTable *openbootSymtab;
+
+ /** Object pointer for the reset binary */
+ ObjectFile *reset;
+
+ /** Object pointer for the hypervisor code */
+ ObjectFile *hypervisor;
+
+ /** Object pointer for the openboot code */
+ ObjectFile *openboot;
+
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ /** Add a function-based event to reset binary. */
+ template <class T>
+ T *SparcSystem::addResetFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(resetSymtab, lbl);
+ }
+
+ /** Add a function-based event to the hypervisor. */
+ template <class T>
+ T *SparcSystem::addHypervisorFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(hypervisorSymtab, lbl);
+ }
+
+ /** Add a function-based event to the openboot. */
+ template <class T>
+ T *SparcSystem::addOpenbootFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(openbootSymtab, lbl);
+ }
+
+ virtual Addr fixFuncEventAddr(Addr addr);
+
+};
+
+#endif
+
diff --git a/arch/sparc/utility.hh b/arch/sparc/utility.hh
new file mode 100644
index 000000000..1e67b3370
--- /dev/null
+++ b/arch/sparc/utility.hh
@@ -0,0 +1,89 @@
+/*
+ * 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_UTILITY_HH__
+#define __ARCH_SPARC_UTILITY_HH__
+
+#include "arch/sparc/isa_traits.hh"
+#include "base/misc.hh"
+
+namespace SparcISA
+{
+ inline ExtMachInst
+ makeExtMI(MachInst inst, const Addr &pc) {
+ return ExtMachInst(inst);
+ }
+
+ inline bool isCallerSaveIntegerRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ inline bool isCallerSaveFloatRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ inline bool isCalleeSaveFloatRegister(unsigned int reg) {
+ panic("register classification not implemented");
+ return false;
+ }
+
+ // 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>
+ void zeroRegisters(XC *xc);
+
+} // namespace SparcISA
+
+#endif
diff --git a/base/chunk_generator.hh b/base/chunk_generator.hh
new file mode 100644
index 000000000..4f708bd4b
--- /dev/null
+++ b/base/chunk_generator.hh
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#ifndef __BASE__CHUNK_GENERATOR_HH__
+#define __BASE__CHUNK_GENERATOR_HH__
+
+/**
+ * @file
+ * Declaration and inline definition of ChunkGenerator object.
+ */
+
+#include <algorithm>
+#include "base/intmath.hh"
+#include "arch/isa_traits.hh" // for Addr
+
+/**
+ * This class takes an arbitrary memory region (address/length pair)
+ * and generates a series of appropriately (e.g. block- or page-)
+ * aligned chunks covering the same region.
+ *
+ * Example usage:
+
+\code
+ for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
+ doSomethingChunky(gen.addr(), gen.size());
+ }
+\endcode
+ */
+class ChunkGenerator
+{
+ private:
+ /** The starting address of the current chunk. */
+ Addr curAddr;
+ /** The starting address of the next chunk (after the current one). */
+ Addr nextAddr;
+ /** The size of the current chunk (in bytes). */
+ int curSize;
+ /** The number of bytes remaining in the region after the current chunk. */
+ int sizeLeft;
+ /** The start address so we can calculate offset in writing block. */
+ const Addr startAddr;
+ /** The maximum chunk size, e.g., the cache block size or page size. */
+ const int chunkSize;
+
+ public:
+ /**
+ * Constructor.
+ * @param startAddr The starting address of the region.
+ * @param totalSize The total size of the region.
+ * @param _chunkSize The size/alignment of chunks into which
+ * the region should be decomposed.
+ */
+ ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize)
+ : startAddr(_startAddr), chunkSize(_chunkSize)
+ {
+ // chunkSize must be a power of two
+ assert(chunkSize == 0 || isPowerOf2(chunkSize));
+
+ // set up initial chunk.
+ curAddr = startAddr;
+
+ if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
+ {
+ nextAddr = startAddr + totalSize;
+ }
+ else
+ {
+ // nextAddr should be *next* chunk start
+ nextAddr = roundUp(startAddr, chunkSize);
+ if (curAddr == nextAddr) {
+ // ... even if startAddr is already chunk-aligned
+ nextAddr += chunkSize;
+ }
+ }
+
+ // how many bytes are left between curAddr and the end of this chunk?
+ int left_in_chunk = nextAddr - curAddr;
+ curSize = std::min(totalSize, left_in_chunk);
+ sizeLeft = totalSize - curSize;
+ }
+
+ /** Return starting address of current chunk. */
+ Addr addr() { return curAddr; }
+ /** Return size in bytes of current chunk. */
+ int size() { return curSize; }
+
+ /** Number of bytes we have already chunked up. */
+ int complete() { return curAddr - startAddr; }
+ /**
+ * Are we done? That is, did the last call to next() advance
+ * past the end of the region?
+ * @return True if yes, false if more to go.
+ */
+ bool done() { return (curSize == 0); }
+
+ /**
+ * Advance generator to next chunk.
+ * @return True if successful, false if unsuccessful
+ * (because we were at the last chunk).
+ */
+ bool next()
+ {
+ if (sizeLeft == 0) {
+ curSize = 0;
+ return false;
+ }
+
+ curAddr = nextAddr;
+ curSize = std::min(sizeLeft, chunkSize);
+ sizeLeft -= curSize;
+ nextAddr += curSize;
+ return true;
+ }
+};
+
+#endif // __BASE__CHUNK_GENERATOR_HH__
diff --git a/base/inet.hh b/base/inet.hh
index e07e01935..e5d0473f9 100644
--- a/base/inet.hh
+++ b/base/inet.hh
@@ -117,11 +117,11 @@ class EthPtr
{
protected:
friend class IpPtr;
- PacketPtr p;
+ EthPacketPtr p;
public:
EthPtr() {}
- EthPtr(const PacketPtr &ptr) : p(ptr) { }
+ EthPtr(const EthPacketPtr &ptr) : p(ptr) { }
EthHdr *operator->() { return (EthHdr *)p->data; }
EthHdr &operator*() { return *(EthHdr *)p->data; }
@@ -131,10 +131,10 @@ class EthPtr
const EthHdr &operator*() const { return *(const EthHdr *)p->data; }
operator const EthHdr *() const { return (const EthHdr *)p->data; }
- const EthPtr &operator=(const PacketPtr &ptr) { p = ptr; return *this; }
+ const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; }
- const PacketPtr packet() const { return p; }
- PacketPtr packet() { return p; }
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
};
@@ -174,13 +174,13 @@ class IpPtr
protected:
friend class TcpPtr;
friend class UdpPtr;
- PacketPtr p;
+ EthPacketPtr p;
const IpHdr *h() const
{ return (const IpHdr *)(p->data + sizeof(eth_hdr)); }
IpHdr *h() { return (IpHdr *)(p->data + sizeof(eth_hdr)); }
- void set(const PacketPtr &ptr)
+ void set(const EthPacketPtr &ptr)
{
EthHdr *eth = (EthHdr *)ptr->data;
if (eth->type() == ETH_TYPE_IP)
@@ -191,7 +191,7 @@ class IpPtr
public:
IpPtr() {}
- IpPtr(const PacketPtr &ptr) { set(ptr); }
+ IpPtr(const EthPacketPtr &ptr) { set(ptr); }
IpPtr(const EthPtr &ptr) { set(ptr.p); }
IpPtr(const IpPtr &ptr) : p(ptr.p) { }
@@ -203,12 +203,12 @@ class IpPtr
const IpHdr &operator*() const { return *h(); }
operator const IpHdr *() const { return h(); }
- const IpPtr &operator=(const PacketPtr &ptr) { set(ptr); return *this; }
+ const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; }
const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; }
const IpPtr &operator=(const IpPtr &ptr) { p = ptr.p; return *this; }
- const PacketPtr packet() const { return p; }
- PacketPtr packet() { return p; }
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
operator bool() { return p; }
@@ -272,13 +272,13 @@ struct TcpHdr : public tcp_hdr
class TcpPtr
{
protected:
- PacketPtr p;
+ EthPacketPtr p;
int off;
const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); }
TcpHdr *h() { return (TcpHdr *)(p->data + off); }
- void set(const PacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
void set(const IpPtr &ptr)
{
if (ptr->proto() == IP_PROTO_TCP)
@@ -303,8 +303,8 @@ class TcpPtr
const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; }
const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; }
- const PacketPtr packet() const { return p; }
- PacketPtr packet() { return p; }
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
operator bool() { return p; }
@@ -362,13 +362,13 @@ struct UdpHdr : public udp_hdr
class UdpPtr
{
protected:
- PacketPtr p;
+ EthPacketPtr p;
int off;
const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); }
UdpHdr *h() { return (UdpHdr *)(p->data + off); }
- void set(const PacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
void set(const IpPtr &ptr)
{
if (ptr->proto() == IP_PROTO_UDP)
@@ -393,8 +393,8 @@ class UdpPtr
const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; }
- const PacketPtr packet() const { return p; }
- PacketPtr packet() { return p; }
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
operator bool() { return p; }
diff --git a/base/intmath.hh b/base/intmath.hh
index df0687c62..51baddb91 100644
--- a/base/intmath.hh
+++ b/base/intmath.hh
@@ -186,9 +186,9 @@ roundUp(T val, int align)
template <class T>
inline T
-roundDown(T val, T align)
+roundDown(T val, int align)
{
- T mask = align - 1;
+ T mask = (T)align - 1;
return val & ~mask;
}
diff --git a/base/loader/aout_object.cc b/base/loader/aout_object.cc
index c81f7123f..564898ca3 100644
--- a/base/loader/aout_object.cc
+++ b/base/loader/aout_object.cc
@@ -30,7 +30,6 @@
#include "base/loader/aout_object.hh"
-#include "mem/functional/functional.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
@@ -64,12 +63,15 @@ AoutObject::AoutObject(const string &_filename, int _fd,
text.baseAddr = N_TXTADDR(*execHdr);
text.size = execHdr->tsize;
+ text.fileImage = fileData + N_TXTOFF(*execHdr);
data.baseAddr = N_DATADDR(*execHdr);
data.size = execHdr->dsize;
+ data.fileImage = fileData + N_DATOFF(*execHdr);
bss.baseAddr = N_BSSADDR(*execHdr);
bss.size = execHdr->bsize;
+ bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
@@ -78,28 +80,6 @@ AoutObject::AoutObject(const string &_filename, int _fd,
bool
-AoutObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Addr textAddr = text.baseAddr;
- Addr dataAddr = data.baseAddr;
-
- if (loadPhys) {
- textAddr &= (ULL(1) << 40) - 1;
- dataAddr &= (ULL(1) << 40) - 1;
- }
-
- // Since we don't really have an MMU and all memory is
- // zero-filled, there's no need to set up the BSS segment.
- if (text.size != 0)
- mem->prot_write(textAddr, fileData + N_TXTOFF(*execHdr), text.size);
- if (data.size != 0)
- mem->prot_write(dataAddr, fileData + N_DATOFF(*execHdr), data.size);
-
- return true;
-}
-
-
-bool
AoutObject::loadGlobalSymbols(SymbolTable *symtab)
{
// a.out symbols not supported yet
diff --git a/base/loader/aout_object.hh b/base/loader/aout_object.hh
index 1868192b2..aeb710427 100644
--- a/base/loader/aout_object.hh
+++ b/base/loader/aout_object.hh
@@ -46,8 +46,6 @@ class AoutObject : public ObjectFile
public:
virtual ~AoutObject() {}
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab);
virtual bool loadLocalSymbols(SymbolTable *symtab);
diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc
index 353a5f333..80917ee9c 100644
--- a/base/loader/ecoff_object.cc
+++ b/base/loader/ecoff_object.cc
@@ -29,8 +29,7 @@
#include <string>
#include "base/loader/ecoff_object.hh"
-
-#include "mem/functional/functional.hh"
+#include "base/misc.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
@@ -68,12 +67,15 @@ EcoffObject::EcoffObject(const string &_filename, int _fd,
text.baseAddr = aoutHdr->text_start;
text.size = aoutHdr->tsize;
+ text.fileImage = fileData + ECOFF_TXTOFF(execHdr);
data.baseAddr = aoutHdr->data_start;
data.size = aoutHdr->dsize;
+ data.fileImage = fileData + ECOFF_DATOFF(execHdr);
bss.baseAddr = aoutHdr->bss_start;
bss.size = aoutHdr->bsize;
+ bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
@@ -82,26 +84,6 @@ EcoffObject::EcoffObject(const string &_filename, int _fd,
bool
-EcoffObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Addr textAddr = text.baseAddr;
- Addr dataAddr = data.baseAddr;
-
- if (loadPhys) {
- textAddr &= (ULL(1) << 40) - 1;
- dataAddr &= (ULL(1) << 40) - 1;
- }
-
- // Since we don't really have an MMU and all memory is
- // zero-filled, there's no need to set up the BSS segment.
- mem->prot_write(textAddr, fileData + ECOFF_TXTOFF(execHdr), text.size);
- mem->prot_write(dataAddr, fileData + ECOFF_DATOFF(execHdr), data.size);
-
- return true;
-}
-
-
-bool
EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
{
if (!symtab)
diff --git a/base/loader/ecoff_object.hh b/base/loader/ecoff_object.hh
index 78aa7f3f7..603c70bec 100644
--- a/base/loader/ecoff_object.hh
+++ b/base/loader/ecoff_object.hh
@@ -50,8 +50,6 @@ class EcoffObject : public ObjectFile
public:
virtual ~EcoffObject() {}
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab);
virtual bool loadLocalSymbols(SymbolTable *symtab);
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc
index 791c6f6de..a104719af 100644
--- a/base/loader/elf_object.cc
+++ b/base/loader/elf_object.cc
@@ -42,12 +42,14 @@
#include "libelf/gelf.h"
#include "base/loader/elf_object.hh"
+#include "base/misc.hh"
-#include "mem/functional/functional.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
+#include "sim/byteswap.hh"
+
using namespace std;
@@ -73,14 +75,8 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
DPRINTFR(Loader, "Not ELF\n");
elf_end(elf);
return NULL;
- }
- else {
+ } else {
//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.
@@ -90,7 +86,7 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
arch = ObjectFile::SPARC;
} else if (ehdr.e_machine == EM_MIPS
&& ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
- arch = ObjectFile::MIPS;
+ arch = ObjectFile::Mips;
} else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
arch = ObjectFile::Alpha;
} else {
@@ -154,6 +150,7 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
section = elf_getscn(elf, ++secIdx);
} // while sections
}
+
elf_end(elf);
return new ElfObject(fname, fd, len, data, arch, opSys);
}
@@ -185,6 +182,7 @@ ElfObject::ElfObject(const string &_filename, int _fd,
entry = ehdr.e_entry;
+
// initialize segment sizes to 0 in case they're not present
text.size = data.size = bss.size = 0;
@@ -203,20 +201,18 @@ ElfObject::ElfObject(const string &_filename, int _fd,
if (text.size == 0) { // haven't seen text segment yet
text.baseAddr = phdr.p_vaddr;
text.size = phdr.p_filesz;
- // remember where the data is for loadSections()
- fileTextBits = fileData + phdr.p_offset;
+ text.fileImage = fileData + phdr.p_offset;
// if there's any padding at the end that's not in the
// file, call it the bss. This happens in the "text"
// segment if there's only one loadable segment (as for
// kernel images).
bss.size = phdr.p_memsz - phdr.p_filesz;
bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
- }
- else if (data.size == 0) { // have text, this must be data
+ bss.fileImage = NULL;
+ } else if (data.size == 0) { // have text, this must be data
data.baseAddr = phdr.p_vaddr;
data.size = phdr.p_filesz;
- // remember where the data is for loadSections()
- fileDataBits = fileData + phdr.p_offset;
+ data.fileImage = fileData + phdr.p_offset;
// if there's any padding at the end that's not in the
// file, call it the bss. Warn if this happens for both
// the text & data segments (should only have one bss).
@@ -225,6 +221,11 @@ ElfObject::ElfObject(const string &_filename, int _fd,
}
bss.size = phdr.p_memsz - phdr.p_filesz;
bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ bss.fileImage = NULL;
+ } else {
+ warn("More than two loadable segments in ELF object.");
+ warn("Ignoring segment @ 0x%x length 0x%x.",
+ phdr.p_vaddr, phdr.p_filesz);
}
}
@@ -242,28 +243,6 @@ ElfObject::ElfObject(const string &_filename, int _fd,
bool
-ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Addr textAddr = text.baseAddr;
- Addr dataAddr = data.baseAddr;
-
- if (loadPhys) {
- textAddr &= (ULL(1) << 40) - 1;
- dataAddr &= (ULL(1) << 40) - 1;
- }
-
- // Since we don't really have an MMU and all memory is
- // zero-filled, there's no need to set up the BSS segment.
- if (text.size != 0)
- mem->prot_write(textAddr, fileTextBits, text.size);
- if (data.size != 0)
- mem->prot_write(dataAddr, fileDataBits, data.size);
-
- return true;
-}
-
-
-bool
ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding)
{
Elf *elf;
diff --git a/base/loader/elf_object.hh b/base/loader/elf_object.hh
index 66d8b3e63..72c265edd 100644
--- a/base/loader/elf_object.hh
+++ b/base/loader/elf_object.hh
@@ -35,9 +35,6 @@ class ElfObject : public ObjectFile
{
protected:
- uint8_t *fileTextBits; //!< Pointer to file's text segment image
- uint8_t *fileDataBits; //!< Pointer to file's data segment image
-
/// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
bool loadSomeSymbols(SymbolTable *symtab, int binding);
@@ -48,8 +45,6 @@ class ElfObject : public ObjectFile
public:
virtual ~ElfObject() {}
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab);
virtual bool loadLocalSymbols(SymbolTable *symtab);
diff --git a/base/loader/object_file.cc b/base/loader/object_file.cc
index 1410d05b8..c6dfced1d 100644
--- a/base/loader/object_file.cc
+++ b/base/loader/object_file.cc
@@ -43,6 +43,8 @@
#include "base/loader/aout_object.hh"
#include "base/loader/elf_object.hh"
+#include "mem/translating_port.hh"
+
using namespace std;
ObjectFile::ObjectFile(const string &_filename, int _fd,
@@ -60,6 +62,32 @@ ObjectFile::~ObjectFile()
}
+bool
+ObjectFile::loadSection(Section *sec, Port *memPort, Addr addrMask)
+{
+ if (sec->size != 0) {
+ Addr addr = sec->baseAddr & addrMask;
+ if (sec->fileImage) {
+ memPort->writeBlob(addr, sec->fileImage, sec->size);
+ }
+ else {
+ // no image: must be bss
+ memPort->memsetBlob(addr, 0, sec->size);
+ }
+ }
+ return true;
+}
+
+
+bool
+ObjectFile::loadSections(Port *memPort, Addr addrMask)
+{
+ return (loadSection(&text, memPort, addrMask)
+ && loadSection(&data, memPort, addrMask)
+ && loadSection(&bss, memPort, addrMask));
+}
+
+
void
ObjectFile::close()
{
diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh
index 1b44ae14f..b43989cb5 100644
--- a/base/loader/object_file.hh
+++ b/base/loader/object_file.hh
@@ -29,11 +29,12 @@
#ifndef __OBJECT_FILE_HH__
#define __OBJECT_FILE_HH__
+#include <limits>
#include <string>
#include "sim/host.hh" // for Addr
-class FunctionalMemory;
+class Port;
class SymbolTable;
class ObjectFile
@@ -44,7 +45,7 @@ class ObjectFile
UnknownArch,
Alpha,
SPARC,
- MIPS
+ Mips
};
enum OpSys {
@@ -72,8 +73,8 @@ class ObjectFile
void close();
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false) = 0;
+ virtual bool loadSections(Port *memPort, Addr addrMask =
+ std::numeric_limits<Addr>::max());
virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
@@ -83,8 +84,9 @@ class ObjectFile
protected:
struct Section {
- Addr baseAddr;
- size_t size;
+ Addr baseAddr;
+ uint8_t *fileImage;
+ size_t size;
};
Addr entry;
@@ -94,8 +96,12 @@ class ObjectFile
Section data;
Section bss;
+ bool loadSection(Section *sec, Port *memPort, Addr addrMask);
+ void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; }
+
public:
Addr entryPoint() const { return entry; }
+
Addr globalPointer() const { return globalPtr; }
Addr textBase() const { return text.baseAddr; }
diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc
index 84093459c..6b85bc680 100644
--- a/base/remote_gdb.cc
+++ b/base/remote_gdb.cc
@@ -120,16 +120,18 @@
#include <string>
#include <unistd.h>
+#include "arch/vtophys.hh"
#include "base/intmath.hh"
#include "base/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
+#include "config/full_system.hh"
#include "cpu/exec_context.hh"
#include "cpu/static_inst.hh"
-#include "mem/functional/physical.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
#include "sim/system.hh"
-#include "arch/vtophys.hh"
using namespace std;
using namespace TheISA;
@@ -372,7 +374,7 @@ RemoteGDB::acc(Addr va, size_t len)
return true;
Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
- TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va);
+ TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va);
if (!pte.valid()) {
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
return false;
@@ -440,7 +442,7 @@ RemoteGDB::getregs()
#ifdef KGDB_FP_REGS
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
- gdbregs[i + KGDB_REG_F0] = context->readFloatRegInt(i);
+ gdbregs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
}
#endif
}
@@ -467,7 +469,7 @@ RemoteGDB::setregs()
#ifdef KGDB_FP_REGS
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
- context->setFloatRegInt(i, gdbregs[i + KGDB_REG_F0]);
+ context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]);
}
#endif
context->setPC(gdbregs[KGDB_REG_PC]);
@@ -632,51 +634,20 @@ RemoteGDB::read(Addr vaddr, size_t size, char *data)
static Addr lastaddr = 0;
static size_t lastsize = 0;
- uint8_t *maddr;
-
if (vaddr < 10) {
DPRINTF(GDBRead, "read: reading memory location zero!\n");
vaddr = lastaddr + lastsize;
}
DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
-#if TRACING_ON
- char *d = data;
- size_t s = size;
-#endif
-
- lastaddr = vaddr;
- lastsize = size;
- size_t count = min((Addr)size,
- VMPageSize - (vaddr & (VMPageSize - 1)));
-
- maddr = vtomem(context, vaddr, count);
- memcpy(data, maddr, count);
-
- vaddr += count;
- data += count;
- size -= count;
-
- while (size >= VMPageSize) {
- maddr = vtomem(context, vaddr, count);
- memcpy(data, maddr, VMPageSize);
-
- vaddr += VMPageSize;
- data += VMPageSize;
- size -= VMPageSize;
- }
-
- if (size > 0) {
- maddr = vtomem(context, vaddr, count);
- memcpy(data, maddr, size);
- }
+ context->getVirtPort(context)->readBlob(vaddr, (uint8_t*)data, size);
#if TRACING_ON
if (DTRACE(GDBRead)) {
if (DTRACE(GDBExtra)) {
char buf[1024];
- mem2hex(buf, d, s);
+ mem2hex(buf, data, size);
DPRINTFNR(": %s\n", buf);
} else
DPRINTFNR("\n");
@@ -693,8 +664,6 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data)
static Addr lastaddr = 0;
static size_t lastsize = 0;
- uint8_t *maddr;
-
if (vaddr < 10) {
DPRINTF(GDBWrite, "write: writing memory location zero!\n");
vaddr = lastaddr + lastsize;
@@ -710,32 +679,7 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data)
DPRINTFNR("\n");
}
- lastaddr = vaddr;
- lastsize = size;
-
- size_t count = min((Addr)size,
- VMPageSize - (vaddr & (VMPageSize - 1)));
-
- maddr = vtomem(context, vaddr, count);
- memcpy(maddr, data, count);
-
- vaddr += count;
- data += count;
- size -= count;
-
- while (size >= VMPageSize) {
- maddr = vtomem(context, vaddr, count);
- memcpy(maddr, data, VMPageSize);
-
- vaddr += VMPageSize;
- data += VMPageSize;
- size -= VMPageSize;
- }
-
- if (size > 0) {
- maddr = vtomem(context, vaddr, count);
- memcpy(maddr, data, size);
- }
+ context->getVirtPort(context)->writeBlob(vaddr, (uint8_t*)data, size);
#ifdef IMB
alpha_pal_imb();
diff --git a/base/timebuf.hh b/base/timebuf.hh
index 435803fae..f6b5b2781 100644
--- a/base/timebuf.hh
+++ b/base/timebuf.hh
@@ -31,8 +31,6 @@
#include <vector>
-using namespace std;
-
template <class T>
class TimeBuffer
{
@@ -42,7 +40,7 @@ class TimeBuffer
int size;
char *data;
- vector<char *> index;
+ std::vector<char *> index;
int base;
void valid(int idx)
diff --git a/base/traceflags.py b/base/traceflags.py
index e814a00fb..7dbaac60e 100644
--- a/base/traceflags.py
+++ b/base/traceflags.py
@@ -142,6 +142,8 @@ baseFlags = [
'OoOCPU',
'HWPrefetch',
'Stack',
+ 'SimpleCPU',
+ 'Sparc',
]
#
diff --git a/build/SConstruct b/build/SConstruct
index 306d3a9dc..28940fc5a 100644
--- a/build/SConstruct
+++ b/build/SConstruct
@@ -231,6 +231,11 @@ sticky_opts = Options(args=ARGUMENTS)
sticky_opts.AddOptions(
EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']),
BoolOption('FULL_SYSTEM', 'Full-system support', False),
+ # There's a bug in scons 0.96.1 that causes ListOptions with list
+ # values (more than one value) not to be able to be restored from
+ # a saved option file. If this causes trouble then upgrade to
+ # scons 0.96.90 or later.
+ ListOption('CPU_MODELS', 'CPU models', 'all', env['ALL_CPU_LIST']),
BoolOption('ALPHA_TLASER',
'Model Alpha TurboLaser platform (vs. Tsunami)', False),
BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
@@ -254,12 +259,6 @@ 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)
)
@@ -329,6 +328,11 @@ env.Append(BUILDERS = { 'ConfigFile' : config_builder })
# rename base env
base_env = env
+help_text = '''
+Usage: scons [scons options] [build options] [target(s)]
+
+'''
+
for build_dir in build_dirs:
# Make a copy of the default environment to use for this config.
env = base_env.Copy()
@@ -362,6 +366,11 @@ for build_dir in build_dirs:
sticky_opts.Update(env)
nonsticky_opts.Update(env)
+ help_text += "Sticky options for %s:\n" % build_dir \
+ + sticky_opts.GenerateHelpText(env) \
+ + "\nNon-sticky options for %s:\n" % build_dir \
+ + nonsticky_opts.GenerateHelpText(env)
+
# Process option settings.
if not have_fenv and env['USE_FENV']:
@@ -410,6 +419,8 @@ for build_dir in build_dirs:
build_dir = os.path.join(build_dir, 'test', e.Label),
exports = { 'env' : e }, duplicate = False)
+Help(help_text)
+
###################################################
#
# Let SCons do its thing. At this point SCons will use the defined
diff --git a/configs/test/SysPaths.py b/configs/test/SysPaths.py
new file mode 100644
index 000000000..7f231916c
--- /dev/null
+++ b/configs/test/SysPaths.py
@@ -0,0 +1,32 @@
+from m5 import *
+
+import os.path
+import sys
+
+# Edit the following list to include the possible paths to the binary
+# and disk image directories. The first directory on the list that
+# exists will be selected.
+SYSTEMDIR_PATH = ['/n/poolfs/z/dist/m5/system']
+
+SYSTEMDIR = None
+for d in SYSTEMDIR_PATH:
+ if os.path.exists(d):
+ SYSTEMDIR = d
+ break
+
+if not SYSTEMDIR:
+ print >>sys.stderr, "Can't find a path to system files."
+ sys.exit(1)
+
+BINDIR = SYSTEMDIR + '/binaries'
+DISKDIR = SYSTEMDIR + '/disks'
+
+def disk(file):
+ return '%s/%s' % (DISKDIR, file)
+
+def binary(file):
+ return '%s/%s' % (BINDIR, file)
+
+def script(file):
+ return '%s/%s' % ('/z/saidi/work/m5.newmem/configs/boot', file)
+
diff --git a/configs/test/fs.py b/configs/test/fs.py
new file mode 100644
index 000000000..ce121bd76
--- /dev/null
+++ b/configs/test/fs.py
@@ -0,0 +1,215 @@
+from m5 import *
+import os
+from SysPaths import *
+
+# Base for tests is directory containing this file.
+test_base = os.path.dirname(__file__)
+
+linux_image = env.get('LINUX_IMAGE', disk('linux-latest.img'))
+
+class IdeControllerPciData(PciConfigData):
+ VendorID = 0x8086
+ DeviceID = 0x7111
+ Command = 0x0
+ Status = 0x280
+ Revision = 0x0
+ ClassCode = 0x01
+ SubClassCode = 0x01
+ ProgIF = 0x85
+ BAR0 = 0x00000001
+ BAR1 = 0x00000001
+ BAR2 = 0x00000001
+ BAR3 = 0x00000001
+ BAR4 = 0x00000001
+ BAR5 = 0x00000001
+ InterruptLine = 0x1f
+ InterruptPin = 0x01
+ BAR0Size = '8B'
+ BAR1Size = '4B'
+ BAR2Size = '8B'
+ BAR3Size = '4B'
+ BAR4Size = '16B'
+
+class SinicPciData(PciConfigData):
+ VendorID = 0x1291
+ DeviceID = 0x1293
+ Status = 0x0290
+ SubClassCode = 0x00
+ ClassCode = 0x02
+ ProgIF = 0x00
+ BAR0 = 0x00000000
+ BAR1 = 0x00000000
+ BAR2 = 0x00000000
+ BAR3 = 0x00000000
+ BAR4 = 0x00000000
+ BAR5 = 0x00000000
+ MaximumLatency = 0x34
+ MinimumGrant = 0xb0
+ InterruptLine = 0x1e
+ InterruptPin = 0x01
+ BAR0Size = '64kB'
+
+class NSGigEPciData(PciConfigData):
+ VendorID = 0x100B
+ DeviceID = 0x0022
+ Status = 0x0290
+ SubClassCode = 0x00
+ ClassCode = 0x02
+ ProgIF = 0x00
+ BAR0 = 0x00000001
+ BAR1 = 0x00000000
+ BAR2 = 0x00000000
+ BAR3 = 0x00000000
+ BAR4 = 0x00000000
+ BAR5 = 0x00000000
+ MaximumLatency = 0x34
+ MinimumGrant = 0xb0
+ InterruptLine = 0x1e
+ InterruptPin = 0x01
+ BAR0Size = '256B'
+ BAR1Size = '4kB'
+
+class LinuxRootDisk(IdeDisk):
+ raw_image = RawDiskImage(image_file=linux_image, read_only=True)
+ image = CowDiskImage(child=Parent.raw_image, read_only=False)
+
+class LinuxSwapDisk(IdeDisk):
+ raw_image = RawDiskImage(image_file = disk('linux-bigswap2.img'),
+ read_only=True)
+ image = CowDiskImage(child = Parent.raw_image, read_only=False)
+
+class SpecwebFilesetDisk(IdeDisk):
+ raw_image = RawDiskImage(image_file = disk('specweb-fileset.img'),
+ read_only=True)
+ image = CowDiskImage(child = Parent.raw_image, read_only=False)
+
+class BaseTsunami(Tsunami):
+ cchip = TsunamiCChip(pio_addr=0x801a0000000)
+ pchip = TsunamiPChip(pio_addr=0x80180000000)
+ pciconfig = PciConfigAll(pio_addr=0x801fe000000)
+ fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
+
+ fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
+ fake_uart2 = IsaFake(pio_addr=0x801fc0003e8)
+ fake_uart3 = IsaFake(pio_addr=0x801fc0002e8)
+ fake_uart4 = IsaFake(pio_addr=0x801fc0003f0)
+
+ fake_ppc = IsaFake(pio_addr=0x801fc0003bc)
+
+ fake_OROM = IsaFake(pio_addr=0x800000a0000, pio_size=0x60000)
+
+ fake_pnp_addr = IsaFake(pio_addr=0x801fc000279)
+ fake_pnp_write = IsaFake(pio_addr=0x801fc000a79)
+ fake_pnp_read0 = IsaFake(pio_addr=0x801fc000203)
+ fake_pnp_read1 = IsaFake(pio_addr=0x801fc000243)
+ fake_pnp_read2 = IsaFake(pio_addr=0x801fc000283)
+ fake_pnp_read3 = IsaFake(pio_addr=0x801fc0002c3)
+ fake_pnp_read4 = IsaFake(pio_addr=0x801fc000303)
+ fake_pnp_read5 = IsaFake(pio_addr=0x801fc000343)
+ fake_pnp_read6 = IsaFake(pio_addr=0x801fc000383)
+ fake_pnp_read7 = IsaFake(pio_addr=0x801fc0003c3)
+
+ fake_ata0 = IsaFake(pio_addr=0x801fc0001f0)
+ fake_ata1 = IsaFake(pio_addr=0x801fc000170)
+
+ fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer')
+ io = TsunamiIO(pio_addr=0x801fc000000)
+ uart = Uart8250(pio_addr=0x801fc0003f8)
+ ethernet = NSGigE(configdata=NSGigEPciData(),
+ pci_bus=0, pci_dev=1, pci_func=0)
+ etherint = NSGigEInt(device=Parent.ethernet)
+# ethernet = Sinic(configdata=SinicPciData(),
+# pci_bus=0, pci_dev=1, pci_func=0)
+# etherint = SinicInt(device=Parent.ethernet)
+ console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk)
+# bridge = PciFake(configdata=BridgePciData(), pci_bus=0, pci_dev=2, pci_func=0)
+
+#class FreeBSDTsunami(BaseTsunami):
+# disk0 = FreeBSDRootDisk(delay='0us', driveID='master')
+# ide = IdeController(disks=[Parent.disk0],
+# configdata=IdeControllerPciData(),
+# pci_func=0, pci_dev=0, pci_bus=0)
+
+class LinuxTsunami(BaseTsunami):
+ disk0 = LinuxRootDisk(driveID='master')
+ disk1 = SpecwebFilesetDisk(driveID='slave')
+ disk2 = LinuxSwapDisk(driveID='master')
+ ide = IdeController(disks=[Parent.disk0, Parent.disk1, Parent.disk2],
+ configdata=IdeControllerPciData(),
+ pci_func=0, pci_dev=0, pci_bus=0)
+
+class LinuxAlphaSystem(LinuxAlphaSystem):
+ magicbus = Bus(bus_id=0)
+ magicbus2 = Bus(bus_id=1)
+ bridge = Bridge()
+ physmem = PhysicalMemory(range = AddrRange('128MB'))
+ c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a")
+ c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b")
+ c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
+ tsunami = LinuxTsunami()
+ c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
+ c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
+ c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus)
+ c5 = Connector(side_a=Parent.tsunami.fake_sm_chip, side_a_name='pio', side_b=Parent.magicbus)
+ c6 = Connector(side_a=Parent.tsunami.ethernet, side_a_name='pio', side_b=Parent.magicbus)
+ c6a = Connector(side_a=Parent.tsunami.ethernet, side_a_name='dma', side_b=Parent.magicbus)
+ c7 = Connector(side_a=Parent.tsunami.fake_uart1, side_a_name='pio', side_b=Parent.magicbus)
+ c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus)
+ c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus)
+ c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus)
+ c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus)
+ c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus)
+ c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus)
+ c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus)
+ c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus)
+ c17 = Connector(side_a=Parent.tsunami.fake_pnp_write, side_a_name='pio', side_b=Parent.magicbus)
+ c18 = Connector(side_a=Parent.tsunami.fake_pnp_read0, side_a_name='pio', side_b=Parent.magicbus)
+ c19 = Connector(side_a=Parent.tsunami.fake_pnp_read1, side_a_name='pio', side_b=Parent.magicbus)
+ c20 = Connector(side_a=Parent.tsunami.fake_pnp_read2, side_a_name='pio', side_b=Parent.magicbus)
+ c21 = Connector(side_a=Parent.tsunami.fake_pnp_read3, side_a_name='pio', side_b=Parent.magicbus)
+ c22 = Connector(side_a=Parent.tsunami.fake_pnp_read4, side_a_name='pio', side_b=Parent.magicbus)
+ c23 = Connector(side_a=Parent.tsunami.fake_pnp_read5, side_a_name='pio', side_b=Parent.magicbus)
+ c24 = Connector(side_a=Parent.tsunami.fake_pnp_read6, side_a_name='pio', side_b=Parent.magicbus)
+ c25 = Connector(side_a=Parent.tsunami.fake_pnp_read7, side_a_name='pio', side_b=Parent.magicbus)
+ c27 = Connector(side_a=Parent.tsunami.fake_ata0, side_a_name='pio', side_b=Parent.magicbus)
+ c28 = Connector(side_a=Parent.tsunami.fake_ata1, side_a_name='pio', side_b=Parent.magicbus)
+ c30 = Connector(side_a=Parent.tsunami.fb, side_a_name='pio', side_b=Parent.magicbus)
+ c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus)
+ c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus)
+ c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus)
+ raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
+ read_only=True)
+ simple_disk = SimpleDisk(disk=Parent.raw_image)
+ intrctrl = IntrControl()
+ cpu = SimpleCPU(mem=Parent.magicbus2)
+ sim_console = SimConsole(listener=ConsoleListener(port=3456))
+ kernel = '/z/saidi/work/m5.newmem/build/vmlinux'
+ pal = binary('ts_osfpal')
+ console = binary('console')
+ boot_osflags = 'root=/dev/hda1 console=ttyS0'
+# readfile = os.path.join(test_base, 'halt.sh')
+
+
+BaseCPU.itb = AlphaITB()
+BaseCPU.dtb = AlphaDTB()
+BaseCPU.system = Parent.any
+
+class TsunamiRoot(System):
+ pass
+
+
+def DualRoot(ClientSystem, ServerSystem):
+ self = Root()
+ self.client = ClientSystem()
+ self.server = ServerSystem()
+
+ self.etherdump = EtherDump(file='ethertrace')
+ self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0],
+ int2 = Parent.server.tsunami.etherint[0],
+ dump = Parent.etherdump)
+ self.clock = '5GHz'
+ return self
+
+root = DualRoot(ClientSystem = LinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')),
+ ServerSystem = LinuxAlphaSystem(readfile=script('netperf-server.rcS')))
+
diff --git a/configs/test/hello b/configs/test/hello
new file mode 100755
index 000000000..59c0d195c
--- /dev/null
+++ b/configs/test/hello
Binary files differ
diff --git a/configs/test/hello_mips b/configs/test/hello_mips
new file mode 100755
index 000000000..a3db001ec
--- /dev/null
+++ b/configs/test/hello_mips
Binary files differ
diff --git a/configs/test/hello_sparc b/configs/test/hello_sparc
new file mode 100755
index 000000000..e254ae33f
--- /dev/null
+++ b/configs/test/hello_sparc
Binary files differ
diff --git a/configs/test/test.py b/configs/test/test.py
new file mode 100644
index 000000000..695d84b73
--- /dev/null
+++ b/configs/test/test.py
@@ -0,0 +1,12 @@
+from m5 import *
+
+class HelloWorld(AlphaLiveProcess):
+ executable = '../configs/test/hello'
+ cmd = 'hello'
+
+magicbus = Bus()
+mem = PhysicalMemory()
+cpu = SimpleCPU(workload=HelloWorld(), mem=magicbus)
+system = System(physmem=mem, cpu=cpu)
+system.c1 = Connector(side_a=mem, side_b=magicbus)
+root = Root(system=system)
diff --git a/cpu/base.cc b/cpu/base.cc
index 2eb5f7fd3..9ce458c64 100644
--- a/cpu/base.cc
+++ b/cpu/base.cc
@@ -65,7 +65,7 @@ BaseCPU::BaseCPU(Params *p)
#else
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), params(p),
- number_of_threads(p->numberOfThreads)
+ number_of_threads(p->numberOfThreads), system(p->system)
#endif
{
DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
@@ -229,6 +229,7 @@ BaseCPU::registerExecContexts()
{
for (int i = 0; i < execContexts.size(); ++i) {
ExecContext *xc = execContexts[i];
+
#if FULL_SYSTEM
int id = params->cpu_id;
if (id != -1)
diff --git a/cpu/base.hh b/cpu/base.hh
index d9d5d2b88..79700c117 100644
--- a/cpu/base.hh
+++ b/cpu/base.hh
@@ -38,11 +38,8 @@
#include "sim/sim_object.hh"
#include "arch/isa_traits.hh"
-#if FULL_SYSTEM
class System;
namespace Kernel { class Statistics; }
-#endif
-
class BranchPred;
class ExecContext;
@@ -123,8 +120,8 @@ class BaseCPU : public SimObject
Tick clock;
bool functionTrace;
Tick functionTraceStart;
-#if FULL_SYSTEM
System *system;
+#if FULL_SYSTEM
int cpu_id;
Tick profile;
#endif
@@ -173,9 +170,9 @@ class BaseCPU : public SimObject
*/
EventQueue **comLoadEventQueue;
-#if FULL_SYSTEM
System *system;
+#if FULL_SYSTEM
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc
index b7238e73a..ec1e94561 100644
--- a/cpu/cpu_exec_context.cc
+++ b/cpu/cpu_exec_context.cc
@@ -28,6 +28,7 @@
#include <string>
+#include "arch/isa_traits.hh"
#include "cpu/base.hh"
#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
@@ -41,10 +42,11 @@
#include "kern/kernel_stats.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
-#include "sim/system.hh"
#include "arch/stacktrace.hh"
#else
#include "sim/process.hh"
+#include "sim/system.hh"
+#include "mem/translating_port.hh"
#endif
using namespace std;
@@ -52,16 +54,16 @@ using namespace std;
// constructor
#if FULL_SYSTEM
CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
- AlphaITB *_itb, AlphaDTB *_dtb,
- FunctionalMemory *_mem)
+ AlphaITB *_itb, AlphaDTB *_dtb)
: _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
- 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)
+ cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb),
+ dtb(_dtb), profile(NULL), quiesceEvent(this), func_exe_inst(0),
+ storeCondFailures(0)
+
{
proxy = new ProxyExecContext<CPUExecContext>(this);
- memset(&regs, 0, sizeof(RegFile));
+ regs.clear();
if (cpu->params->profile) {
profile = new FunctionProfile(system->kernelSymtab);
@@ -76,30 +78,39 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
static ProfileNode dummyNode;
profileNode = &dummyNode;
profilePC = 3;
+
+ Port *mem_port;
+ physPort = new FunctionalPort();
+ mem_port = system->physmem->getPort("functional");
+ mem_port->setPeer(physPort);
+ physPort->setPeer(mem_port);
+
+ virtPort = new VirtualPort();
+ mem_port = system->physmem->getPort("functional");
+ mem_port->setPeer(virtPort);
+ virtPort->setPeer(mem_port);
}
#else
CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid)
+ Process *_process, int _asid, MemObject* memobj)
: _status(ExecContext::Unallocated),
cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
- lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(&regs, 0, sizeof(RegFile));
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- FunctionalMemory *_mem, int _asid)
- : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
+ lastSuspend(0), process(_process), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
- memset(&regs, 0, sizeof(RegFile));
+ /* Use this port to for syscall emulation writes to memory. */
+ Port *mem_port;
+ port = new TranslatingPort(process->pTable, false);
+ mem_port = memobj->getPort("functional");
+ mem_port->setPeer(port);
+ port->setPeer(mem_port);
+
+ regs.clear();
proxy = new ProxyExecContext<CPUExecContext>(this);
}
CPUExecContext::CPUExecContext(RegFile *regFile)
- : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1),
+ : cpu(NULL), thread_num(-1), process(NULL), asid(-1),
func_exe_inst(0), storeCondFailures(0)
{
regs = *regFile;
@@ -158,7 +169,6 @@ void
CPUExecContext::takeOverFrom(ExecContext *oldContext)
{
// some things should already be set up
- assert(mem == oldContext->getMemPtr());
#if FULL_SYSTEM
assert(system == oldContext->getSystemPtr());
#else
@@ -277,22 +287,34 @@ CPUExecContext::regStats(const string &name)
void
CPUExecContext::copyArchRegs(ExecContext *xc)
{
- // First loop through the integer registers.
- for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
- setIntReg(i, xc->readIntReg(i));
- }
+ TheISA::copyRegs(xc, proxy);
+}
- // 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));
- }
+#if FULL_SYSTEM
+VirtualPort*
+CPUExecContext::getVirtPort(ExecContext *xc)
+{
+ if (!xc)
+ return virtPort;
- // Copy misc. registers
- regs.miscRegs.copyMiscRegs(xc);
+ VirtualPort *vp;
+ Port *mem_port;
- // Lastly copy PC/NPC
- setPC(xc->readPC());
- setNextPC(xc->readNextPC());
+ vp = new VirtualPort(xc);
+ mem_port = system->physmem->getPort("functional");
+ mem_port->setPeer(vp);
+ vp->setPeer(mem_port);
+ return vp;
}
+void
+CPUExecContext::delVirtPort(VirtualPort *vp)
+{
+// assert(!vp->nullExecContext());
+ delete vp->getPeer();
+ delete vp;
+}
+
+
+#endif
+
diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh
index beaf67352..2c06a7b3b 100644
--- a/cpu/cpu_exec_context.hh
+++ b/cpu/cpu_exec_context.hh
@@ -32,16 +32,13 @@
#include "arch/isa_traits.hh"
#include "config/full_system.hh"
#include "cpu/exec_context.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_req.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"
-// forward declaration: see functional_memory.hh
-class FunctionalMemory;
-class PhysicalMemory;
class BaseCPU;
#if FULL_SYSTEM
@@ -51,11 +48,16 @@ class BaseCPU;
class FunctionProfile;
class ProfileNode;
-class MemoryController;
+class FunctionalPort;
+class PhysicalPort;
+
#else // !FULL_SYSTEM
#include "sim/process.hh"
+#include "mem/page_table.hh"
+class TranslatingPort;
+
#endif // FULL_SYSTEM
@@ -72,6 +74,8 @@ class CPUExecContext
typedef TheISA::MachInst MachInst;
typedef TheISA::MiscRegFile MiscRegFile;
typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
public:
typedef ExecContext::Status Status;
@@ -118,17 +122,20 @@ class CPUExecContext
Tick lastActivate;
Tick lastSuspend;
+ System *system;
+
+
#if FULL_SYSTEM
- FunctionalMemory *mem;
AlphaITB *itb;
AlphaDTB *dtb;
- System *system;
- // 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;
+ /** A functional port outgoing only for functional accesses to physical
+ * addresses.*/
+ FunctionalPort *physPort;
+
+ /** A functional port, outgoing only, for functional accesse to virtual
+ * addresses. That doen't require execution context information */
+ VirtualPort *virtPort;
FunctionProfile *profile;
ProfileNode *profileNode;
@@ -162,9 +169,10 @@ class CPUExecContext
void profileSample();
#else
- Process *process;
+ /// Port that syscalls can use to access memory (provides translation step).
+ TranslatingPort *port;
- FunctionalMemory *mem; // functional storage for process address space
+ Process *process;
// Address space ID. Note that this is used for TIMING cache
// simulation only; all functional memory accesses should use
@@ -200,11 +208,10 @@ class CPUExecContext
// constructor: initialize context from given process structure
#if FULL_SYSTEM
CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
+ AlphaITB *_itb, AlphaDTB *_dtb);
#else
- CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
- CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid);
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid,
+ MemObject *memobj);
// Constructor to use XC to pass reg file around. Not used for anything
// else.
CPUExecContext(RegFile *regFile);
@@ -227,74 +234,67 @@ class CPUExecContext
#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(MemReqPtr &req)
+ Fault translateInstReq(RequestPtr &req)
{
- return itb->translate(req);
+ return itb->translate(req, proxy);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault translateDataReadReq(RequestPtr &req)
{
- return dtb->translate(req, false);
+ return dtb->translate(req, proxy, false);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault translateDataWriteReq(RequestPtr &req)
{
- return dtb->translate(req, true);
+ return dtb->translate(req, proxy, true);
}
-#else
- Process *getProcessPtr() { return process; }
+ FunctionalPort *getPhysPort() { return physPort; }
- bool validInstAddr(Addr addr)
- { return process->validInstAddr(addr); }
+ /** Return a virtual port. If no exec context is specified then a static
+ * port is returned. Otherwise a port is created and returned. It must be
+ * deleted by deleteVirtPort(). */
+ VirtualPort *getVirtPort(ExecContext *xc);
- bool validDataAddr(Addr addr)
- { return process->validDataAddr(addr); }
+ void delVirtPort(VirtualPort *vp);
+
+#else
+ TranslatingPort *getMemPort() { return port; }
+
+ Process *getProcessPtr() { return process; }
int getInstAsid() { return asid; }
int getDataAsid() { return asid; }
- Fault dummyTranslation(MemReqPtr &req)
- {
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
-#endif
-
- // 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 NoFault;
- }
- Fault translateInstReq(MemReqPtr &req)
+ Fault translateInstReq(RequestPtr &req)
{
- return dummyTranslation(req);
+ return process->pTable->translate(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+
+ Fault translateDataReadReq(RequestPtr &req)
{
- return dummyTranslation(req);
+ return process->pTable->translate(req);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+
+ Fault translateDataWriteReq(RequestPtr &req)
{
- return dummyTranslation(req);
+ return process->pTable->translate(req);
}
#endif
+/*
template <class T>
- Fault read(MemReqPtr &req, T &data)
+ Fault read(RequestPtr &req, T &data)
{
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
+#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
if (req->flags & LOCKED) {
req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
@@ -302,15 +302,15 @@ class CPUExecContext
#endif
Fault error;
- error = mem->read(req, data);
+ error = mem->prot_read(req->paddr, data, req->size);
data = LittleEndianGuest::gtoh(data);
return error;
}
template <class T>
- Fault write(MemReqPtr &req, T &data)
+ Fault write(RequestPtr &req, T &data)
{
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
+#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
ExecContext *xc;
// If this is a store conditional, act appropriately
@@ -356,9 +356,9 @@ class CPUExecContext
}
#endif
- return mem->write(req, (T)LittleEndianGuest::htog(data));
+ return mem->prot_write(req->paddr, (T)htog(data), req->size);
}
-
+*/
virtual bool misspeculating();
@@ -369,17 +369,17 @@ class CPUExecContext
inst = new_inst;
}
- Fault instRead(MemReqPtr &req)
+ Fault instRead(RequestPtr &req)
{
- return mem->read(req, inst);
+ panic("instRead not implemented");
+ // return funcPhysMem->read(req, inst);
+ return NoFault;
}
void setCpuId(int id) { cpu_id = id; }
int readCpuId() { return cpu_id; }
- FunctionalMemory *getMemPtr() { return mem; }
-
void copyArchRegs(ExecContext *xc);
//
@@ -387,93 +387,103 @@ class CPUExecContext
//
uint64_t readIntReg(int reg_idx)
{
- return regs.intRegFile[reg_idx];
+ return regs.readIntReg(reg_idx);
}
- float readFloatRegSingle(int reg_idx)
+ FloatReg readFloatReg(int reg_idx, int width)
{
- return (float)regs.floatRegFile.d[reg_idx];
+ return regs.readFloatReg(reg_idx, width);
}
- double readFloatRegDouble(int reg_idx)
+ FloatReg readFloatReg(int reg_idx)
{
- return regs.floatRegFile.d[reg_idx];
+ return regs.readFloatReg(reg_idx);
}
- uint64_t readFloatRegInt(int reg_idx)
+ FloatRegBits readFloatRegBits(int reg_idx, int width)
{
- return regs.floatRegFile.q[reg_idx];
+ return regs.readFloatRegBits(reg_idx, width);
+ }
+
+ FloatRegBits readFloatRegBits(int reg_idx)
+ {
+ return regs.readFloatRegBits(reg_idx);
}
void setIntReg(int reg_idx, uint64_t val)
{
- regs.intRegFile[reg_idx] = val;
+ regs.setIntReg(reg_idx, val);
}
- void setFloatRegSingle(int reg_idx, float val)
+ void setFloatReg(int reg_idx, FloatReg val, int width)
{
- regs.floatRegFile.d[reg_idx] = (double)val;
+ regs.setFloatReg(reg_idx, val, width);
}
- void setFloatRegDouble(int reg_idx, double val)
+ void setFloatReg(int reg_idx, FloatReg val)
{
- regs.floatRegFile.d[reg_idx] = val;
+ regs.setFloatReg(reg_idx, val);
}
- void setFloatRegInt(int reg_idx, uint64_t val)
+ void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
{
- regs.floatRegFile.q[reg_idx] = val;
+ regs.setFloatRegBits(reg_idx, val, width);
+ }
+
+ void setFloatRegBits(int reg_idx, FloatRegBits val)
+ {
+ regs.setFloatRegBits(reg_idx, val);
}
uint64_t readPC()
{
- return regs.pc;
+ return regs.readPC();
}
void setPC(uint64_t val)
{
- regs.pc = val;
+ regs.setPC(val);
}
uint64_t readNextPC()
{
- return regs.npc;
+ return regs.readNextPC();
}
void setNextPC(uint64_t val)
{
- regs.npc = val;
+ regs.setNextPC(val);
}
uint64_t readNextNPC()
{
- return regs.nnpc;
+ return regs.readNextNPC();
}
void setNextNPC(uint64_t val)
{
- regs.nnpc = val;
+ regs.setNextNPC(val);
}
MiscReg readMiscReg(int misc_reg)
{
- return regs.miscRegs.readReg(misc_reg);
+ return regs.readMiscReg(misc_reg);
}
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{
- return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
+ return regs.readMiscRegWithEffect(misc_reg, fault, proxy);
}
Fault setMiscReg(int misc_reg, const MiscReg &val)
{
- return regs.miscRegs.setReg(misc_reg, val);
+ return regs.setMiscReg(misc_reg, val);
}
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
{
- return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy);
+ return regs.setMiscRegWithEffect(misc_reg, val, proxy);
}
unsigned readStCondFailures() { return storeCondFailures; }
@@ -481,26 +491,26 @@ class CPUExecContext
void setStCondFailures(unsigned sc_failures)
{ storeCondFailures = sc_failures; }
- void clearArchRegs() { memset(&regs, 0, sizeof(regs)); }
+ void clearArchRegs() { regs.clear(); }
#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 inPalMode() { return AlphaISA::PcPAL(regs.readPC()); }
bool simPalCheck(int palFunc);
#endif
#if !FULL_SYSTEM
TheISA::IntReg getSyscallArg(int i)
{
- return regs.intRegFile[TheISA::ArgumentReg0 + i];
+ return regs.readIntReg(TheISA::ArgumentReg0 + i);
}
// used to shift args for indirect syscall
void setSyscallArg(int i, TheISA::IntReg val)
{
- regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
+ regs.setIntReg(TheISA::ArgumentReg0 + i, val);
}
void setSyscallReturn(SyscallReturn return_value)
@@ -508,15 +518,21 @@ class CPUExecContext
TheISA::setSyscallReturn(return_value, &regs);
}
- void syscall()
+ void syscall(int64_t callnum)
{
- process->syscall(proxy);
+ process->syscall(callnum, proxy);
}
Counter readFuncExeInst() { return func_exe_inst; }
void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
#endif
+
+ void changeRegFileContext(RegFile::ContextParam param,
+ RegFile::ContextVal val)
+ {
+ regs.changeContext(param, val);
+ }
};
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index 2b6c41bd7..1f26183ab 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -30,21 +30,21 @@
#define __CPU_EXEC_CONTEXT_HH__
#include "config/full_system.hh"
-#include "mem/mem_req.hh"
+#include "mem/request.hh"
#include "sim/faults.hh"
#include "sim/host.hh"
#include "sim/serialize.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;
class Event;
-class FunctionalMemory;
-class PhysicalMemory;
+class TranslatingPort;
+class FunctionalPort;
+class VirtualPort;
class Process;
class System;
@@ -54,6 +54,8 @@ class ExecContext
typedef TheISA::RegFile RegFile;
typedef TheISA::MachInst MachInst;
typedef TheISA::IntReg IntReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscRegFile MiscRegFile;
typedef TheISA::MiscReg MiscReg;
public:
@@ -87,17 +89,21 @@ class ExecContext
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;
+
+ virtual FunctionalPort *getPhysPort() = 0;
+
+ virtual VirtualPort *getVirtPort(ExecContext *xc = NULL) = 0;
+
+ virtual void delVirtPort(VirtualPort *vp) = 0;
#else
+ virtual TranslatingPort *getMemPort() = 0;
+
virtual Process *getProcessPtr() = 0;
#endif
@@ -143,16 +149,14 @@ class ExecContext
virtual int getThreadNum() = 0;
- virtual bool validInstAddr(Addr addr) = 0;
- virtual bool validDataAddr(Addr addr) = 0;
virtual int getInstAsid() = 0;
virtual int getDataAsid() = 0;
- virtual Fault translateInstReq(MemReqPtr &req) = 0;
+ virtual Fault translateInstReq(RequestPtr &req) = 0;
- virtual Fault translateDataReadReq(MemReqPtr &req) = 0;
+ virtual Fault translateDataReadReq(RequestPtr &req) = 0;
- virtual Fault translateDataWriteReq(MemReqPtr &req) = 0;
+ virtual Fault translateDataWriteReq(RequestPtr &req) = 0;
// Also somewhat obnoxious. Really only used for the TLB fault.
// However, may be quite useful in SPARC.
@@ -167,19 +171,23 @@ class ExecContext
//
virtual uint64_t readIntReg(int reg_idx) = 0;
- virtual float readFloatRegSingle(int reg_idx) = 0;
+ virtual FloatReg readFloatReg(int reg_idx, int width) = 0;
- virtual double readFloatRegDouble(int reg_idx) = 0;
+ virtual FloatReg readFloatReg(int reg_idx) = 0;
- virtual uint64_t readFloatRegInt(int reg_idx) = 0;
+ virtual FloatRegBits readFloatRegBits(int reg_idx, int width) = 0;
+
+ virtual FloatRegBits readFloatRegBits(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 setFloatReg(int reg_idx, FloatReg val, int width) = 0;
+
+ virtual void setFloatReg(int reg_idx, FloatReg val) = 0;
- virtual void setFloatRegDouble(int reg_idx, double val) = 0;
+ virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0;
- virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0;
+ virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width) = 0;
virtual uint64_t readPC() = 0;
@@ -189,6 +197,10 @@ class ExecContext
virtual void setNextPC(uint64_t val) = 0;
+ virtual uint64_t readNextNPC() = 0;
+
+ virtual void setNextNPC(uint64_t val) = 0;
+
virtual MiscReg readMiscReg(int misc_reg) = 0;
virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0;
@@ -222,13 +234,16 @@ class ExecContext
virtual void setSyscallReturn(SyscallReturn return_value) = 0;
- virtual void syscall() = 0;
+ virtual void syscall(int64_t callnum) = 0;
// Same with st cond failures.
virtual Counter readFuncExeInst() = 0;
virtual void setFuncExeInst(Counter new_val) = 0;
#endif
+
+ virtual void changeRegFileContext(RegFile::ContextParam param,
+ RegFile::ContextVal val) = 0;
};
template <class XC>
@@ -249,17 +264,21 @@ class ProxyExecContext : public ExecContext
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(); }
+
+ FunctionalPort *getPhysPort() { return actualXC->getPhysPort(); }
+
+ VirtualPort *getVirtPort(ExecContext *xc = NULL) { return actualXC->getVirtPort(xc); }
+
+ void delVirtPort(VirtualPort *vp) { return actualXC->delVirtPort(vp); }
#else
+ TranslatingPort *getMemPort() { return actualXC->getMemPort(); }
+
Process *getProcessPtr() { return actualXC->getProcessPtr(); }
#endif
@@ -305,18 +324,16 @@ class ProxyExecContext : public ExecContext
int getThreadNum() { return actualXC->getThreadNum(); }
- 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(); }
- Fault translateInstReq(MemReqPtr &req)
+ Fault translateInstReq(RequestPtr &req)
{ return actualXC->translateInstReq(req); }
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault translateDataReadReq(RequestPtr &req)
{ return actualXC->translateDataReadReq(req); }
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault translateDataWriteReq(RequestPtr &req)
{ return actualXC->translateDataWriteReq(req); }
// @todo: Do I need this?
@@ -333,26 +350,32 @@ class ProxyExecContext : public ExecContext
uint64_t readIntReg(int reg_idx)
{ return actualXC->readIntReg(reg_idx); }
- float readFloatRegSingle(int reg_idx)
- { return actualXC->readFloatRegSingle(reg_idx); }
+ FloatReg readFloatReg(int reg_idx, int width)
+ { return actualXC->readFloatReg(reg_idx, width); }
+
+ FloatReg readFloatReg(int reg_idx)
+ { return actualXC->readFloatReg(reg_idx); }
- double readFloatRegDouble(int reg_idx)
- { return actualXC->readFloatRegDouble(reg_idx); }
+ FloatRegBits readFloatRegBits(int reg_idx, int width)
+ { return actualXC->readFloatRegBits(reg_idx, width); }
- uint64_t readFloatRegInt(int reg_idx)
- { return actualXC->readFloatRegInt(reg_idx); }
+ FloatRegBits readFloatRegBits(int reg_idx)
+ { return actualXC->readFloatRegBits(reg_idx); }
void setIntReg(int reg_idx, uint64_t val)
{ actualXC->setIntReg(reg_idx, val); }
- void setFloatRegSingle(int reg_idx, float val)
- { actualXC->setFloatRegSingle(reg_idx, val); }
+ void setFloatReg(int reg_idx, FloatReg val, int width)
+ { actualXC->setFloatReg(reg_idx, val, width); }
- void setFloatRegDouble(int reg_idx, double val)
- { actualXC->setFloatRegDouble(reg_idx, val); }
+ void setFloatReg(int reg_idx, FloatReg val)
+ { actualXC->setFloatReg(reg_idx, val); }
- void setFloatRegInt(int reg_idx, uint64_t val)
- { actualXC->setFloatRegInt(reg_idx, val); }
+ void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
+ { actualXC->setFloatRegBits(reg_idx, val, width); }
+
+ void setFloatRegBits(int reg_idx, FloatRegBits val)
+ { actualXC->setFloatRegBits(reg_idx, val); }
uint64_t readPC() { return actualXC->readPC(); }
@@ -362,6 +385,10 @@ class ProxyExecContext : public ExecContext
void setNextPC(uint64_t val) { actualXC->setNextPC(val); }
+ uint64_t readNextNPC() { return actualXC->readNextNPC(); }
+
+ void setNextNPC(uint64_t val) { actualXC->setNextNPC(val); }
+
MiscReg readMiscReg(int misc_reg)
{ return actualXC->readMiscReg(misc_reg); }
@@ -405,13 +432,19 @@ class ProxyExecContext : public ExecContext
void setSyscallReturn(SyscallReturn return_value)
{ actualXC->setSyscallReturn(return_value); }
- void syscall() { actualXC->syscall(); }
+ void syscall(int64_t callnum) { actualXC->syscall(callnum); }
Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
void setFuncExeInst(Counter new_val)
{ return actualXC->setFuncExeInst(new_val); }
#endif
+
+ void changeRegFileContext(RegFile::ContextParam param,
+ RegFile::ContextVal val)
+ {
+ actualXC->changeRegFileContext(param, val);
+ }
};
#endif
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
index 84b5eacf7..0ed3b43c4 100644
--- a/cpu/exetrace.cc
+++ b/cpu/exetrace.cc
@@ -29,14 +29,12 @@
#include <fstream>
#include <iomanip>
-#include "sim/param.hh"
-#include "encumbered/cpu/full/dyn_inst.hh"
-#include "encumbered/cpu/full/spec_state.hh"
-#include "encumbered/cpu/full/issue.hh"
-#include "cpu/exetrace.hh"
#include "base/loader/symtab.hh"
#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
#include "cpu/static_inst.hh"
+#include "sim/param.hh"
+#include "sim/system.hh"
using namespace std;
@@ -130,10 +128,11 @@ Trace::InstRecord::dump(ostream &outs)
outs << " A=0x" << hex << addr;
if (flags[PRINT_INT_REGS] && regs_valid) {
- for (int i = 0; i < 32;)
+ for (int i = 0; i < TheISA::NumIntRegs;)
for (int j = i + 1; i <= j; i++)
- ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i],
- ((i == j) ? "\n" : " "));
+ ccprintf(outs, "r%02d = %#018x%s", i,
+ iregs->regs.readReg(i),
+ ((i == j) ? "\n" : " "));
outs << "\n";
}
diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh
index 67d042ec8..a26cdc517 100644
--- a/cpu/exetrace.hh
+++ b/cpu/exetrace.hh
@@ -163,7 +163,7 @@ InstRecord::setRegs(const IntRegFile &regs)
if (!iregs)
iregs = new iRegFile;
- memcpy(&iregs->regs, regs, sizeof(IntRegFile));
+ memcpy(&iregs->regs, &regs, sizeof(IntRegFile));
regs_valid = true;
}
diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh
index 0352e9972..8e1e0f42a 100644
--- a/cpu/o3/alpha_cpu.hh
+++ b/cpu/o3/alpha_cpu.hh
@@ -208,7 +208,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
template <class T>
Fault read(MemReqPtr &req, T &data)
{
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
+#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
if (req->flags & LOCKED) {
req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
@@ -230,7 +230,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
template <class T>
Fault write(MemReqPtr &req, T &data)
{
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
+#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
ExecContext *xc;
// If this is a store conditional, act appropriately
diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh
index 9f1fa24f6..7c4c2b969 100644
--- a/cpu/o3/alpha_cpu_impl.hh
+++ b/cpu/o3/alpha_cpu_impl.hh
@@ -175,10 +175,8 @@ AlphaFullCPU<Impl>::copyToXC()
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
- this->cpuXC->setFloatRegDouble(i,
- this->regFile.readFloatRegDouble(renamed_reg));
- this->cpuXC->setFloatRegInt(i,
- this->regFile.readFloatRegInt(renamed_reg));
+ this->cpuXC->setFloatRegBits(i,
+ this->regFile.readFloatRegBits(renamed_reg));
}
this->cpuXC->setMiscReg(AlphaISA::Fpcr_DepTag,
@@ -223,10 +221,8 @@ AlphaFullCPU<Impl>::copyFromXC()
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
- this->regFile.setFloatRegDouble(renamed_reg,
- this->cpuXC->readFloatRegDouble(i));
- this->regFile.setFloatRegInt(renamed_reg,
- this->cpuXC->readFloatRegInt(i));
+ this->regFile.setFloatRegBits(renamed_reg,
+ this->cpuXC->readFloatRegBits(i));
}
// Then loop through the misc registers.
diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh
index e7f7d3a57..5b8a05e5c 100644
--- a/cpu/o3/alpha_dyn_inst.hh
+++ b/cpu/o3/alpha_dyn_inst.hh
@@ -152,19 +152,24 @@ class AlphaDynInst : public BaseDynInst<Impl>
return this->cpu->readIntReg(_srcRegIdx[idx]);
}
- float readFloatRegSingle(const StaticInst *si, int idx)
+ FloatReg readFloatReg(const StaticInst *si, int idx, int width)
{
- return this->cpu->readFloatRegSingle(_srcRegIdx[idx]);
+ return this->cpu->readFloatReg(_srcRegIdx[idx], width);
}
- double readFloatRegDouble(const StaticInst *si, int idx)
+ FloatReg readFloatReg(const StaticInst *si, int idx)
{
- return this->cpu->readFloatRegDouble(_srcRegIdx[idx]);
+ return this->cpu->readFloatReg(_srcRegIdx[idx]);
}
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
{
- return this->cpu->readFloatRegInt(_srcRegIdx[idx]);
+ return this->cpu->readFloatRegBits(_srcRegIdx[idx], width);
+ }
+
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
+ {
+ return this->cpu->readFloatRegBits(_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
@@ -176,21 +181,28 @@ class AlphaDynInst : public BaseDynInst<Impl>
this->instResult.integer = val;
}
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
{
- this->cpu->setFloatRegSingle(_destRegIdx[idx], val);
+ this->cpu->setFloatReg(_destRegIdx[idx], val, width);
this->instResult.fp = val;
}
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val)
{
- this->cpu->setFloatRegDouble(_destRegIdx[idx], val);
+ this->cpu->setFloatReg(_destRegIdx[idx], val);
this->instResult.dbl = val;
}
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
+ void setFloatRegBits(const StaticInst *si, int idx,
+ FloatRegBits val, int width)
+ {
+ this->cpu->setFloatRegBits(_destRegIdx[idx], val, width);
+ this->instResult.integer = val;
+ }
+
+ void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
{
- this->cpu->setFloatRegInt(_destRegIdx[idx], val);
+ this->cpu->setFloatRegBits(_destRegIdx[idx], val);
this->instResult.integer = val;
}
diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc
index 62d68bb33..a268dbc23 100644
--- a/cpu/o3/cpu.cc
+++ b/cpu/o3/cpu.cc
@@ -258,8 +258,7 @@ FullO3CPU<Impl>::init()
// Then loop through the floating point registers.
for (int i = 0; i < TheISA::NumFloatRegs; ++i)
{
- regFile.floatRegFile[i].d = src_xc->readFloatRegDouble(i);
- regFile.floatRegFile[i].q = src_xc->readFloatRegInt(i);
+ regFile.floatRegFile.setRegBits(i, src_xc->readRegBits(i))
}
/*
// Then loop through the misc registers.
@@ -348,24 +347,31 @@ FullO3CPU<Impl>::readIntReg(int reg_idx)
}
template <class Impl>
-float
-FullO3CPU<Impl>::readFloatRegSingle(int reg_idx)
+FloatReg
+FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
{
- return regFile.readFloatRegSingle(reg_idx);
+ return regFile.readFloatReg(reg_idx, width);
}
template <class Impl>
-double
-FullO3CPU<Impl>::readFloatRegDouble(int reg_idx)
+FloatReg
+FullO3CPU<Impl>::readFloatReg(int reg_idx)
{
- return regFile.readFloatRegDouble(reg_idx);
+ return regFile.readFloatReg(reg_idx);
}
template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readFloatRegInt(int reg_idx)
+FloatRegBits
+FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
+{
+ return regFile.readFloatRegBits(reg_idx, width);
+}
+
+template <class Impl>
+FloatRegBits
+FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
{
- return regFile.readFloatRegInt(reg_idx);
+ return regFile.readFloatRegBits(reg_idx);
}
template <class Impl>
@@ -377,23 +383,30 @@ FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
template <class Impl>
void
-FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val)
+FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
+{
+ regFile.setFloatReg(reg_idx, val, width);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
{
- regFile.setFloatRegSingle(reg_idx, val);
+ regFile.setFloatReg(reg_idx, val);
}
template <class Impl>
void
-FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val)
+FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
{
- regFile.setFloatRegDouble(reg_idx, val);
+ regFile.setFloatRegBits(reg_idx, val, width);
}
template <class Impl>
void
-FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val)
+FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
{
- regFile.setFloatRegInt(reg_idx, val);
+ regFile.setFloatRegBits(reg_idx, val);
}
template <class Impl>
diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh
index 6577e46e4..f7c80e8a1 100644
--- a/cpu/o3/cpu.hh
+++ b/cpu/o3/cpu.hh
@@ -170,19 +170,23 @@ class FullO3CPU : public BaseFullCPU
//
uint64_t readIntReg(int reg_idx);
- float readFloatRegSingle(int reg_idx);
+ FloatReg readFloatReg(int reg_idx);
- double readFloatRegDouble(int reg_idx);
+ FloatReg readFloatReg(int reg_idx, int width);
- uint64_t readFloatRegInt(int reg_idx);
+ FloatRegBits readFloatRegBits(int reg_idx);
+
+ FloatRegBits readFloatRegBits(int reg_idx, int width);
void setIntReg(int reg_idx, uint64_t val);
- void setFloatRegSingle(int reg_idx, float val);
+ void setFloatReg(int reg_idx, FloatReg val, int width);
+
+ void setFloatReg(int reg_idx, FloatReg val, int width);
- void setFloatRegDouble(int reg_idx, double val);
+ void setFloatRegBits(int reg_idx, FloatRegBits val);
- void setFloatRegInt(int reg_idx, uint64_t val);
+ void setFloatRegBits(int reg_idx, FloatRegBits val);
uint64_t readPC();
diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh
index 1e6e10f29..a5cfa8f3c 100644
--- a/cpu/o3/regfile.hh
+++ b/cpu/o3/regfile.hh
@@ -89,43 +89,64 @@ class PhysRegFile
return intRegFile[reg_idx];
}
- float readFloatRegSingle(PhysRegIndex reg_idx)
+ FloatReg readFloatReg(PhysRegIndex reg_idx, int width)
{
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
- DPRINTF(IEW, "RegFile: Access to float register %i as single, has "
- "data %8.8f\n", int(reg_idx), (float)floatRegFile[reg_idx].d);
+ FloatReg floatReg = floatRegFile.readReg(reg_idx, width);
- return (float)floatRegFile[reg_idx].d;
+ DPRINTF(IEW, "RegFile: Access to %d byte float register %i, has "
+ "data %8.8d\n", int(reg_idx), (double)floatReg);
+
+ return floatReg;
}
- double readFloatRegDouble(PhysRegIndex reg_idx)
+ FloatReg readFloatReg(PhysRegIndex reg_idx)
{
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
- DPRINTF(IEW, "RegFile: Access to float register %i as double, has "
- " data %8.8f\n", int(reg_idx), floatRegFile[reg_idx].d);
+ FloatReg floatReg = floatRegFile.readReg(reg_idx);
+
+ DPRINTF(IEW, "RegFile: Access to float register %i, has "
+ "data %8.8d\n", int(reg_idx), (double)floatReg);
- return floatRegFile[reg_idx].d;
+ return floatReg;
}
- uint64_t readFloatRegInt(PhysRegIndex reg_idx)
+ FloatRegBits readFloatRegBits(PhysRegIndex reg_idx, int width)
{
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
- DPRINTF(IEW, "RegFile: Access to float register %i as int, has data "
- "%lli\n", int(reg_idx), floatRegFile[reg_idx].q);
+ FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx, width);
+
+ DPRINTF(IEW, "RegFile: Access to %d byte float register %i as int, "
+ "has data %lli\n", int(reg_idx), (uint64_t)floatRegBits);
+
+ return floatRegBits;
+ }
+
+ FloatRegBits readFloatRegBits(PhysRegIndex reg_idx)
+ {
+ // Remove the base Float reg dependency.
+ reg_idx = reg_idx - numPhysicalIntRegs;
+
+ assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+
+ FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx);
+
+ DPRINTF(IEW, "RegFile: Access to float register %i as int, "
+ "has data %lli\n", int(reg_idx), (uint64_t)floatRegBits);
- return floatRegFile[reg_idx].q;
+ return floatRegBits;
}
void setIntReg(PhysRegIndex reg_idx, uint64_t val)
@@ -138,33 +159,33 @@ class PhysRegFile
intRegFile[reg_idx] = val;
}
- void setFloatRegSingle(PhysRegIndex reg_idx, float val)
+ void setFloatReg(PhysRegIndex reg_idx, FloatReg val, int width)
{
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
- DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n",
- int(reg_idx), val);
+ DPRINTF(IEW, "RegFile: Setting float register %i to %8.8d\n",
+ int(reg_idx), (double)val);
- floatRegFile[reg_idx].d = (double)val;
+ floatRegFile.setReg(reg_idx, val, width);
}
- void setFloatRegDouble(PhysRegIndex reg_idx, double val)
+ void setFloatReg(PhysRegIndex reg_idx, FloatReg val)
{
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
- DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n",
- int(reg_idx), val);
+ DPRINTF(IEW, "RegFile: Setting float register %i to %8.8d\n",
+ int(reg_idx), (double)val);
- floatRegFile[reg_idx].d = val;
+ floatRegFile.setReg(reg_idx, val);
}
- void setFloatRegInt(PhysRegIndex reg_idx, uint64_t val)
+ void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val, int width)
{
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
@@ -172,9 +193,22 @@ class PhysRegFile
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n",
- int(reg_idx), val);
+ int(reg_idx), (uint64_t)val);
+
+ floatRegFile.setRegBits(reg_idx, val, width);
+ }
+
+ void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val)
+ {
+ // Remove the base Float reg dependency.
+ reg_idx = reg_idx - numPhysicalIntRegs;
+
+ assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+
+ DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n",
+ int(reg_idx), (uint64_t)val);
- floatRegFile[reg_idx].q = val;
+ floatRegFile.setRegBits(reg_idx, val);
}
uint64_t readPC()
diff --git a/cpu/op_class.cc b/cpu/op_class.cc
new file mode 100644
index 000000000..00136ded5
--- /dev/null
+++ b/cpu/op_class.cc
@@ -0,0 +1,50 @@
+/*
+ * 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 "cpu/op_class.hh"
+
+/** OpClass enum -> description string */
+const char *
+opClassStrings[Num_OpClasses] =
+{
+ "(null)",
+ "IntAlu",
+ "IntMult",
+ "IntDiv",
+ "FloatAdd",
+ "FloatCmp",
+ "FloatCvt",
+ "FloatMult",
+ "FloatDiv",
+ "FloatSqrt",
+ "MemRead",
+ "MemWrite",
+ "IprAccess",
+ "InstPrefetch"
+};
+
diff --git a/encumbered/cpu/full/op_class.hh b/cpu/op_class.hh
index ff53b58d2..cdb40a0fb 100644
--- a/encumbered/cpu/full/op_class.hh
+++ b/cpu/op_class.hh
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
-#define __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
+#ifndef __CPU__OP_CLASS_HH__
+#define __CPU__OP_CLASS_HH__
/**
* @file
@@ -39,26 +39,26 @@
* assigning instructions to functional units.
*/
enum OpClass {
- No_OpClass = 0, /* inst does not use a functional unit */
- IntAluOp, /* integer ALU */
- IntMultOp, /* integer multiplier */
- IntDivOp, /* integer divider */
- FloatAddOp, /* floating point adder/subtractor */
- FloatCmpOp, /* floating point comparator */
- FloatCvtOp, /* floating point<->integer converter */
- FloatMultOp, /* floating point multiplier */
- FloatDivOp, /* floating point divider */
- FloatSqrtOp, /* floating point square root */
- MemReadOp, /* memory read port */
- MemWriteOp, /* memory write port */
- IprAccessOp, /* Internal Processor Register read/write port */
- InstPrefetchOp, /* instruction prefetch port (on I-cache) */
- Num_OpClasses /* total functional unit classes */
+ No_OpClass = 0, ///< Instruction does not use a functional unit
+ IntAluOp, ///< Integer ALU operaton (add/sub/logical)
+ IntMultOp, ///< Integer multiply
+ IntDivOp, ///< Integer divide
+ FloatAddOp, ///< Floating point add/subtract
+ FloatCmpOp, ///< Floating point comparison
+ FloatCvtOp, ///< Floating point<->integer conversion
+ FloatMultOp, ///< Floating point multiply
+ FloatDivOp, ///< Floating point divide
+ FloatSqrtOp, ///< Floating point square root
+ MemReadOp, ///< Memory read port
+ MemWriteOp, ///< Memory write port
+ IprAccessOp, ///< Internal Processor Register read/write port
+ InstPrefetchOp, ///< Instruction prefetch port (on I-cache)
+ Num_OpClasses ///< Total number of operation classes
};
/**
- * Array mapping OpClass enum values to strings. Defined in fu_pool.cc.
+ * Array mapping OpClass enum values to strings. Defined in op_class.cc.
*/
extern const char *opClassStrings[];
-#endif // __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
+#endif // __CPU__OP_CLASS_HH__
diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh
index f5d84d656..fa849bb09 100644
--- a/cpu/ozone/cpu.hh
+++ b/cpu/ozone/cpu.hh
@@ -406,22 +406,28 @@ class OoOCPU : public BaseCPU
return xc->readIntReg(si->srcRegIdx(idx));
}
- float readFloatRegSingle(StaticInst *si, int idx)
+ FloatReg readFloatReg(StaticInst *si, int idx, width)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegSingle(reg_idx);
+ return xc->readFloatReg(reg_idx, width);
}
- double readFloatRegDouble(StaticInst *si, int idx)
+ FloatReg readFloatReg(StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegDouble(reg_idx);
+ return xc->readFloatReg(reg_idx);
}
- uint64_t readFloatRegInt(StaticInst *si, int idx)
+ FloatRegBits readFloatRegBits(StaticInst *si, int idx, int width)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegInt(reg_idx);
+ return xc->readFloatRegBits(reg_idx, width);
+ }
+
+ FloatRegBits readFloatRegBits(StaticInst *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegBits(reg_idx);
}
void setIntReg(StaticInst *si, int idx, uint64_t val)
@@ -429,22 +435,28 @@ class OoOCPU : public BaseCPU
xc->setIntReg(si->destRegIdx(idx), val);
}
- void setFloatRegSingle(StaticInst *si, int idx, float val)
+ void setFloatReg(StaticInst *si, int idx, FloatReg val, int width)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatReg(reg_idx, val, width);
+ }
+
+ void setFloatReg(StaticInst *si, int idx, FloatReg val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegSingle(reg_idx, val);
+ xc->setFloatReg(reg_idx, val);
}
- void setFloatRegDouble(StaticInst *si, int idx, double val)
+ void setFloatRegBits(StaticInst *si, int idx, FloatRegBits val, int width)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegDouble(reg_idx, val);
+ xc->setFloatRegBits(reg_idx, val, width);
}
- void setFloatRegInt(StaticInst *si, int idx, uint64_t val)
+ void setFloatRegBits(StaticInst *si, int idx, FloatRegBits val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegInt(reg_idx, val);
+ xc->setFloatRegBits(reg_idx, val);
}
uint64_t readPC() { return PC; }
diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh
index 7fa3902cc..32b7f3ef5 100644
--- a/cpu/pc_event.hh
+++ b/cpu/pc_event.hh
@@ -31,7 +31,7 @@
#include <vector>
-#include "mem/mem_req.hh"
+#include "base/misc.hh"
class ExecContext;
class PCEventQueue;
@@ -39,9 +39,6 @@ class PCEventQueue;
class PCEvent
{
protected:
- static const Addr badpc = MemReq::inval_addr;
-
- protected:
std::string description;
PCEventQueue *queue;
Addr evpc;
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
index 8db72b77e..33fe63c26 100644
--- a/cpu/simple/cpu.cc
+++ b/cpu/simple/cpu.cc
@@ -35,6 +35,7 @@
#include <sstream>
#include <string>
+#include "arch/utility.hh"
#include "base/cprintf.hh"
#include "base/inifile.hh"
#include "base/loader/symtab.hh"
@@ -53,8 +54,7 @@
#include "cpu/smt.hh"
#include "cpu/static_inst.hh"
#include "kern/kernel_stats.hh"
-#include "mem/base_mem.hh"
-#include "mem/mem_interface.hh"
+#include "mem/packet_impl.hh"
#include "sim/byteswap.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
@@ -65,20 +65,18 @@
#if FULL_SYSTEM
#include "base/remote_gdb.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+//#include "mem/functional/memory_control.hh"
+//#include "mem/functional/physical.hh"
#include "sim/system.hh"
#include "arch/tlb.hh"
#include "arch/stacktrace.hh"
#include "arch/vtophys.hh"
#else // !FULL_SYSTEM
-#include "mem/functional/functional.hh"
+#include "mem/mem_object.hh"
#endif // FULL_SYSTEM
using namespace std;
-//The SimpleCPU does alpha only
-using namespace AlphaISA;
-
+using namespace TheISA;
SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
: Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
@@ -89,6 +87,15 @@ SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
void
SimpleCPU::init()
{
+ //Create Memory Ports (conect them up)
+ Port *mem_dport = mem->getPort("");
+ dcachePort.setPeer(mem_dport);
+ mem_dport->setPeer(&dcachePort);
+
+ Port *mem_iport = mem->getPort("");
+ icachePort.setPeer(mem_iport);
+ mem_iport->setPeer(&icachePort);
+
BaseCPU::init();
#if FULL_SYSTEM
for (int i = 0; i < execContexts.size(); ++i) {
@@ -116,43 +123,82 @@ SimpleCPU::TickEvent::description()
}
-SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)
- : Event(&mainEventQueue), cpu(_cpu)
+bool
+SimpleCPU::CpuPort::recvTiming(Packet &pkt)
{
+ cpu->processResponse(pkt);
+ return true;
}
-void SimpleCPU::CacheCompletionEvent::process()
+Tick
+SimpleCPU::CpuPort::recvAtomic(Packet &pkt)
{
- cpu->processCacheCompletion();
+ panic("CPU doesn't expect callback!");
+ return curTick;
}
-const char *
-SimpleCPU::CacheCompletionEvent::description()
+void
+SimpleCPU::CpuPort::recvFunctional(Packet &pkt)
+{
+ panic("CPU doesn't expect callback!");
+}
+
+void
+SimpleCPU::CpuPort::recvStatusChange(Status status)
{
- return "SimpleCPU cache completion event";
+ cpu->recvStatusChange(status);
+}
+
+Packet *
+SimpleCPU::CpuPort::recvRetry()
+{
+ return cpu->processRetry();
}
SimpleCPU::SimpleCPU(Params *p)
- : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL),
- cacheCompletionEvent(this)
+ : BaseCPU(p), mem(p->mem), icachePort(this),
+ dcachePort(this), tickEvent(this, p->width), cpuXC(NULL)
{
_status = Idle;
-#if FULL_SYSTEM
- cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
+#if FULL_SYSTEM
+ cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb);
#else
cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process,
- /* asid */ 0);
+ /* asid */ 0, mem);
#endif // !FULL_SYSTEM
- xcProxy = cpuXC->getProxy();
- icacheInterface = p->icache_interface;
- dcacheInterface = p->dcache_interface;
+ xcProxy = cpuXC->getProxy();
- memReq = new MemReq();
- memReq->xc = xcProxy;
- memReq->asid = 0;
- memReq->data = new uint8_t[64];
+#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
+ ifetch_req = new Request(true);
+ ifetch_req->setAsid(0);
+ // @todo fix me and get the real cpu iD!!!
+ ifetch_req->setCpuNum(0);
+ ifetch_req->setSize(sizeof(MachInst));
+ ifetch_pkt = new Packet;
+ ifetch_pkt->cmd = Read;
+ ifetch_pkt->dataStatic(&inst);
+ ifetch_pkt->req = ifetch_req;
+ ifetch_pkt->size = sizeof(MachInst);
+
+ data_read_req = new Request(true);
+ // @todo fix me and get the real cpu iD!!!
+ data_read_req->setCpuNum(0);
+ data_read_req->setAsid(0);
+ data_read_pkt = new Packet;
+ data_read_pkt->cmd = Read;
+ data_read_pkt->dataStatic(&dataReg);
+ data_read_pkt->req = data_read_req;
+
+ data_write_req = new Request(true);
+ // @todo fix me and get the real cpu iD!!!
+ data_write_req->setCpuNum(0);
+ data_write_req->setAsid(0);
+ data_write_pkt = new Packet;
+ data_write_pkt->cmd = Write;
+ data_write_pkt->req = data_write_req;
+#endif
numInst = 0;
startNumInst = 0;
@@ -172,9 +218,9 @@ void
SimpleCPU::switchOut(Sampler *s)
{
sampler = s;
- if (status() == DcacheMissStall) {
+ if (status() == DcacheWaitResponse) {
DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");
- _status = DcacheMissSwitch;
+ _status = DcacheWaitSwitch;
}
else {
_status = SwitchedOut;
@@ -287,6 +333,18 @@ SimpleCPU::regStats()
.prereq(dcacheStallCycles)
;
+ icacheRetryCycles
+ .name(name() + ".icache_retry_cycles")
+ .desc("ICache total retry cycles")
+ .prereq(icacheRetryCycles)
+ ;
+
+ dcacheRetryCycles
+ .name(name() + ".dcache_retry_cycles")
+ .desc("DCache total retry cycles")
+ .prereq(dcacheRetryCycles)
+ ;
+
idleFraction = constant(1.0) - notIdleFraction;
}
@@ -308,7 +366,6 @@ SimpleCPU::serialize(ostream &os)
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
- cacheCompletionEvent.serialize(os);
}
void
@@ -319,8 +376,6 @@ SimpleCPU::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(inst);
cpuXC->unserialize(cp, csprintf("%s.xc", section));
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
- cacheCompletionEvent
- .unserialize(cp, csprintf("%s.cacheCompletionEvent", section));
}
void
@@ -331,6 +386,7 @@ change_thread_state(int thread_number, int activate, int priority)
Fault
SimpleCPU::copySrcTranslate(Addr src)
{
+#if 0
static bool no_warn = true;
int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
// Only support block sizes of 64 atm.
@@ -347,8 +403,7 @@ SimpleCPU::copySrcTranslate(Addr src)
memReq->reset(src & ~(blk_size - 1), blk_size);
- // translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
+ // translate to physical address Fault fault = cpuXC->translateDataReadReq(req);
if (fault == NoFault) {
cpuXC->copySrcAddr = src;
@@ -360,11 +415,15 @@ SimpleCPU::copySrcTranslate(Addr src)
cpuXC->copySrcPhysAddr = 0;
}
return fault;
+#else
+ return NoFault;
+#endif
}
Fault
SimpleCPU::copy(Addr dest)
{
+#if 0
static bool no_warn = true;
int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
// Only support block sizes of 64 atm.
@@ -383,7 +442,7 @@ SimpleCPU::copy(Addr dest)
memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
+ Fault fault = cpuXC->translateDataWriteReq(req);
if (fault == NoFault) {
Addr dest_addr = memReq->paddr + offset;
@@ -407,6 +466,10 @@ SimpleCPU::copy(Addr dest)
assert(!fault->isAlignmentFault());
return fault;
+#else
+ panic("copy not implemented");
+ return NoFault;
+#endif
}
// precise architected memory state accessor macros
@@ -414,22 +477,65 @@ template <class T>
Fault
SimpleCPU::read(Addr addr, T &data, unsigned flags)
{
- if (status() == DcacheMissStall || status() == DcacheMissSwitch) {
- Fault fault = cpuXC->read(memReq,data);
+ if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) {
+// Fault fault = xc->read(memReq,data);
+ // Not sure what to check for no fault...
+ if (data_read_pkt->result == Success) {
+ data = data_read_pkt->get<T>();
+ }
if (traceData) {
- traceData->setAddr(addr);
+ traceData->setAddr(data_read_req->getVaddr());
}
- return fault;
+
+ // @todo: Figure out a way to create a Fault from the packet result.
+ return NoFault;
}
- memReq->reset(addr, sizeof(T), flags);
+// memReq->reset(addr, sizeof(T), flags);
+
+#if SIMPLE_CPU_MEM_TIMING
+ CpuRequest *data_read_req = new Request(true);
+#endif
+
+ data_read_req->setVaddr(addr);
+ data_read_req->setSize(sizeof(T));
+ data_read_req->setFlags(flags);
+ data_read_req->setTime(curTick);
// translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
+ Fault fault = cpuXC->translateDataReadReq(data_read_req);
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
+ // Now do the access.
+ if (fault == NoFault) {
+#if SIMPLE_CPU_MEM_TIMING
+ data_read_pkt = new Packet;
+ data_read_pkt->cmd = Read;
+ data_read_pkt->req = data_read_req;
+ data_read_pkt->data = new uint8_t[8];
+#endif
+ data_read_pkt->reset();
+ data_read_pkt->addr = data_read_req->getPaddr();
+ data_read_pkt->size = sizeof(T);
+
+ sendDcacheRequest(data_read_pkt);
+
+#if SIMPLE_CPU_MEM_IMMEDIATE
+ // Need to find a way to not duplicate code above.
+
+ if (data_read_pkt->result == Success) {
+ data = data_read_pkt->get<T>();
+ }
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ }
+
+ // @todo: Figure out a way to create a Fault from the packet result.
+ return NoFault;
+#endif
+ }
+/*
memReq->cmd = Read;
memReq->completionEvent = NULL;
memReq->time = curTick;
@@ -454,8 +560,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
fault = cpuXC->read(memReq, data);
}
-
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
+*/
+ // This will need a new way to tell if it has a dcache attached.
+ if (data_read_req->getFlags() & UNCACHEABLE)
recordEvent("Uncached Read");
return fault;
@@ -508,11 +615,33 @@ template <class T>
Fault
SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
- memReq->reset(addr, sizeof(T), flags);
+ data_write_req->setVaddr(addr);
+ data_write_req->setTime(curTick);
+ data_write_req->setSize(sizeof(T));
+ data_write_req->setFlags(flags);
// translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
+ Fault fault = cpuXC->translateDataWriteReq(data_write_req);
+ // Now do the access.
+ if (fault == NoFault) {
+#if SIMPLE_CPU_MEM_TIMING
+ data_write_pkt = new Packet;
+ data_write_pkt->cmd = Write;
+ data_write_pkt->req = data_write_req;
+ data_write_pkt->allocate();
+ data_write_pkt->set(data);
+#else
+ data_write_pkt->reset();
+ data = htog(data);
+ data_write_pkt->dataStatic(&data);
+#endif
+ data_write_pkt->addr = data_write_req->getPaddr();
+ data_write_pkt->size = sizeof(T);
+
+ sendDcacheRequest(data_write_pkt);
+ }
+/*
// do functional access
if (fault == NoFault)
fault = cpuXC->write(memReq, data);
@@ -535,13 +664,21 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
_status = DcacheMissStall;
}
}
-
+*/
if (res && (fault == NoFault))
- *res = memReq->result;
+ *res = data_write_pkt->result;
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
+ // This will need a new way to tell if it's hooked up to a cache or not.
+ if (data_write_req->getFlags() & UNCACHEABLE)
recordEvent("Uncached Write");
+ // @todo this is a hack and only works on uniprocessor systems some one else
+ // can implement LL/SC.
+ if (data_write_req->getFlags() & LOCKED)
+ *res = 1;
+
+ // If the write needs to have a fault on the access, consider calling
+ // changeStatus() and changing it to "bad addr write" or something.
return fault;
}
@@ -597,36 +734,130 @@ SimpleCPU::dbg_vtophys(Addr addr)
#endif // FULL_SYSTEM
void
-SimpleCPU::processCacheCompletion()
+SimpleCPU::sendIcacheRequest(Packet *pkt)
{
+ assert(!tickEvent.scheduled());
+#if SIMPLE_CPU_MEM_TIMING
+ retry_pkt = pkt;
+ bool success = icachePort.sendTiming(*pkt);
+
+ unscheduleTickEvent();
+
+ lastIcacheStall = curTick;
+
+ if (!success) {
+ // Need to wait for retry
+ _status = IcacheRetry;
+ } else {
+ // Need to wait for cache to respond
+ _status = IcacheWaitResponse;
+ }
+#elif SIMPLE_CPU_MEM_ATOMIC
+ Tick latency = icachePort.sendAtomic(*pkt);
+
+ unscheduleTickEvent();
+ scheduleTickEvent(latency);
+
+ // Note that Icache miss cycles will be incorrect. Unless
+ // we check the status of the packet sent (is this valid?),
+ // we won't know if the latency is a hit or a miss.
+ icacheStallCycles += latency;
+
+ _status = IcacheAccessComplete;
+#elif SIMPLE_CPU_MEM_IMMEDIATE
+ icachePort.sendAtomic(*pkt);
+#else
+#error "SimpleCPU has no mem model set"
+#endif
+}
+
+void
+SimpleCPU::sendDcacheRequest(Packet *pkt)
+{
+ assert(!tickEvent.scheduled());
+#if SIMPLE_CPU_MEM_TIMING
+ unscheduleTickEvent();
+
+ retry_pkt = pkt;
+ bool success = dcachePort.sendTiming(*pkt);
+
+ lastDcacheStall = curTick;
+
+ if (!success) {
+ _status = DcacheRetry;
+ } else {
+ _status = DcacheWaitResponse;
+ }
+#elif SIMPLE_CPU_MEM_ATOMIC
+ unscheduleTickEvent();
+
+ Tick latency = dcachePort.sendAtomic(*pkt);
+
+ scheduleTickEvent(latency);
+
+ // Note that Dcache miss cycles will be incorrect. Unless
+ // we check the status of the packet sent (is this valid?),
+ // we won't know if the latency is a hit or a miss.
+ dcacheStallCycles += latency;
+#elif SIMPLE_CPU_MEM_IMMEDIATE
+ dcachePort.sendAtomic(*pkt);
+#else
+#error "SimpleCPU has no mem model set"
+#endif
+}
+
+void
+SimpleCPU::processResponse(Packet &response)
+{
+ assert(SIMPLE_CPU_MEM_TIMING);
+
+ // For what things is the CPU the consumer of the packet it sent
+ // out? This may create a memory leak if that's the case and it's
+ // expected of the SimpleCPU to delete its own packet.
+ Packet *pkt = &response;
+
switch (status()) {
- case IcacheMissStall:
+ case IcacheWaitResponse:
icacheStallCycles += curTick - lastIcacheStall;
- _status = IcacheMissComplete;
+
+ _status = IcacheAccessComplete;
scheduleTickEvent(1);
+
+ // Copy the icache data into the instruction itself.
+ inst = pkt->get<MachInst>();
+
+ delete pkt;
break;
- case DcacheMissStall:
- if (memReq->cmd.isRead()) {
+ case DcacheWaitResponse:
+ if (pkt->cmd == Read) {
curStaticInst->execute(this,traceData);
if (traceData)
traceData->finalize();
}
+
+ delete pkt;
+
dcacheStallCycles += curTick - lastDcacheStall;
_status = Running;
scheduleTickEvent(1);
break;
- case DcacheMissSwitch:
- if (memReq->cmd.isRead()) {
+ case DcacheWaitSwitch:
+ if (pkt->cmd == Read) {
curStaticInst->execute(this,traceData);
if (traceData)
traceData->finalize();
}
+
+ delete pkt;
+
_status = SwitchedOut;
sampler->signalSwitched();
case SwitchedOut:
// If this CPU has been switched out due to sampling/warm-up,
// ignore any further status changes (e.g., due to cache
// misses outstanding at the time of the switch).
+ delete pkt;
+
return;
default:
panic("SimpleCPU::processCacheCompletion: bad state");
@@ -634,6 +865,28 @@ SimpleCPU::processCacheCompletion()
}
}
+Packet *
+SimpleCPU::processRetry()
+{
+#if SIMPLE_CPU_MEM_TIMING
+ switch(status()) {
+ case IcacheRetry:
+ icacheRetryCycles += curTick - lastIcacheStall;
+ return retry_pkt;
+ break;
+ case DcacheRetry:
+ dcacheRetryCycles += curTick - lastDcacheStall;
+ return retry_pkt;
+ break;
+ default:
+ panic("SimpleCPU::processRetry: bad state");
+ break;
+ }
+#else
+ panic("shouldn't be here");
+#endif
+}
+
#if FULL_SYSTEM
void
SimpleCPU::post_interrupt(int int_num, int index)
@@ -651,6 +904,8 @@ SimpleCPU::post_interrupt(int int_num, int index)
void
SimpleCPU::tick()
{
+ DPRINTF(SimpleCPU,"\n\n");
+
numCycles++;
traceData = NULL;
@@ -659,7 +914,7 @@ SimpleCPU::tick()
#if FULL_SYSTEM
if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() &&
- status() != IcacheMissComplete) {
+ status() != IcacheAccessComplete) {
int ipl = 0;
int summary = 0;
checkInterrupts = false;
@@ -702,37 +957,57 @@ SimpleCPU::tick()
// maintain $r0 semantics
cpuXC->setIntReg(ZeroReg, 0);
-#ifdef TARGET_ALPHA
- cpuXC->setFloatRegDouble(ZeroReg, 0.0);
-#endif // TARGET_ALPHA
+#if THE_ISA == ALPHA_ISA
+ cpuXC->setFloatReg(ZeroReg, 0.0);
+#endif // ALPHA_ISA
- if (status() == IcacheMissComplete) {
+ if (status() == IcacheAccessComplete) {
// We've already fetched an instruction and were stalled on an
// I-cache miss. No need to fetch it again.
// Set status to running; tick event will get rescheduled if
// necessary at end of tick() function.
_status = Running;
- }
- else {
+ } else {
// Try to fetch an instruction
// set up memory request for instruction fetch
+
+ DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(),
+ cpuXC->readNextPC(),cpuXC->readNextNPC());
+
+#if SIMPLE_CPU_MEM_TIMING
+ CpuRequest *ifetch_req = new CpuRequest();
+ ifetch_req->setSize(sizeof(MachInst));
+#endif
+
+ ifetch_req->resetMin();
+ ifetch_req->setVaddr(cpuXC->readPC() & ~3);
+ ifetch_req->setTime(curTick);
#if FULL_SYSTEM
-#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
+ ifetch_req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0);
#else
-#define IFETCH_FLAGS(pc) 0
+ ifetch_req->setFlags(0);
#endif
- memReq->cmd = Read;
- memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
- IFETCH_FLAGS(cpuXC->readPC()));
-
- fault = cpuXC->translateInstReq(memReq);
+ fault = cpuXC->translateInstReq(ifetch_req);
- if (fault == NoFault)
- fault = cpuXC->mem->read(memReq, inst);
+ if (fault == NoFault) {
+#if SIMPLE_CPU_MEM_TIMING
+ Packet *ifetch_pkt = new Packet;
+ ifetch_pkt->cmd = Read;
+ ifetch_pkt->data = (uint8_t *)&inst;
+ ifetch_pkt->req = ifetch_req;
+ ifetch_pkt->size = sizeof(MachInst);
+#endif
+ ifetch_pkt->reset();
+ ifetch_pkt->addr = ifetch_req->getPaddr();
+ sendIcacheRequest(ifetch_pkt);
+#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC
+ return;
+#endif
+/*
if (icacheInterface && fault == NoFault) {
memReq->completionEvent = NULL;
@@ -743,7 +1018,7 @@ SimpleCPU::tick()
// Ugly hack to get an event scheduled *only* if the access is
// a miss. We really should add first-class support for this
// at some point.
- if (result != MA_HIT && icacheInterface->doEvents()) {
+ if (result != MA_HIT && icacheInterface->doEvents()) {
memReq->completionEvent = &cacheCompletionEvent;
lastIcacheStall = curTick;
unscheduleTickEvent();
@@ -751,6 +1026,8 @@ SimpleCPU::tick()
return;
}
}
+*/
+ }
}
// If we've got a valid instruction (i.e., no fault on instruction
@@ -771,6 +1048,9 @@ SimpleCPU::tick()
traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst,
cpuXC->readPC());
+ DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n",
+ curStaticInst->getName(),curStaticInst->getOpcode(), curStaticInst->machInst);
+
#if FULL_SYSTEM
cpuXC->setInst(inst);
#endif // FULL_SYSTEM
@@ -806,8 +1086,7 @@ SimpleCPU::tick()
// If we have a dcache miss, then we can't finialize the instruction
// trace yet because we want to populate it with the data later
- if (traceData &&
- !(status() == DcacheMissStall && memReq->cmd.isRead())) {
+ if (traceData && (status() != DcacheWaitResponse)) {
traceData->finalize();
}
@@ -819,11 +1098,11 @@ SimpleCPU::tick()
#if FULL_SYSTEM
fault->invoke(xcProxy);
#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
+ fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC());
#endif // FULL_SYSTEM
}
else {
-#if THE_ISA != MIPS_ISA
+#if THE_ISA == ALPHA_ISA
// go to the next instruction
cpuXC->setPC(cpuXC->readNextPC());
cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
@@ -846,7 +1125,7 @@ SimpleCPU::tick()
assert(status() == Running ||
status() == Idle ||
- status() == DcacheMissStall);
+ status() == DcacheWaitResponse);
if (status() == Running && !tickEvent.scheduled())
tickEvent.schedule(curTick + cycles(1));
@@ -862,11 +1141,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
+ SimObjectParam<MemObject *> mem;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
@@ -875,8 +1154,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
#endif // FULL_SYSTEM
Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
Param<bool> defer_registration;
Param<int> width;
@@ -895,11 +1172,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
"terminate when any thread reaches this load count"),
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
+ INIT_PARAM(mem, "memory"),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(mem, "memory"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
@@ -908,8 +1185,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
#endif // FULL_SYSTEM
INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(icache, "L1 instruction cache object"),
- INIT_PARAM(dcache, "L1 data cache object"),
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(width, "cpu width"),
INIT_PARAM(function_trace, "Enable function trace"),
@@ -931,14 +1206,12 @@ CREATE_SIM_OBJECT(SimpleCPU)
params->clock = clock;
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
- params->icache_interface = (icache) ? icache->getInterface() : NULL;
- params->dcache_interface = (dcache) ? dcache->getInterface() : NULL;
params->width = width;
+ params->mem = mem;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->mem = mem;
params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
index 4ab9a1c3e..945de20af 100644
--- a/cpu/simple/cpu.hh
+++ b/cpu/simple/cpu.hh
@@ -36,6 +36,9 @@
#include "cpu/pc_event.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "mem/request.hh"
#include "sim/eventq.hh"
// forward declarations
@@ -43,7 +46,7 @@
class Processor;
class AlphaITB;
class AlphaDTB;
-class PhysicalMemory;
+class MemObject;
class RemoteGDB;
class GDBListener;
@@ -55,18 +58,61 @@ class Process;
#endif // FULL_SYSTEM
class ExecContext;
-class MemInterface;
class Checkpoint;
namespace Trace {
class InstRecord;
}
+
+// Set exactly one of these symbols to 1 to set the memory access
+// model. Probably should make these template parameters, or even
+// just fork the CPU models.
+//
+#define SIMPLE_CPU_MEM_TIMING 0
+#define SIMPLE_CPU_MEM_ATOMIC 0
+#define SIMPLE_CPU_MEM_IMMEDIATE 1
+
+
class SimpleCPU : public BaseCPU
{
protected:
typedef TheISA::MachInst MachInst;
typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
+ class CpuPort : public Port
+ {
+
+ SimpleCPU *cpu;
+
+ public:
+
+ CpuPort(SimpleCPU *_cpu)
+ : cpu(_cpu)
+ { }
+
+ protected:
+
+ virtual bool recvTiming(Packet &pkt);
+
+ virtual Tick recvAtomic(Packet &pkt);
+
+ virtual void recvFunctional(Packet &pkt);
+
+ virtual void recvStatusChange(Status status);
+
+ virtual Packet *recvRetry();
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { resp.clear(); snoop.clear(); }
+ };
+
+ MemObject *mem;
+ CpuPort icachePort;
+ CpuPort dcachePort;
+
public:
// main simulation loop (one cycle)
void tick();
@@ -109,10 +155,12 @@ class SimpleCPU : public BaseCPU
enum Status {
Running,
Idle,
- IcacheMissStall,
- IcacheMissComplete,
- DcacheMissStall,
- DcacheMissSwitch,
+ IcacheRetry,
+ IcacheWaitResponse,
+ IcacheAccessComplete,
+ DcacheRetry,
+ DcacheWaitResponse,
+ DcacheWaitSwitch,
SwitchedOut
};
@@ -133,13 +181,11 @@ class SimpleCPU : public BaseCPU
public:
struct Params : public BaseCPU::Params
{
- MemInterface *icache_interface;
- MemInterface *dcache_interface;
int width;
+ MemObject *mem;
#if FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
- FunctionalMemory *mem;
#else
Process *process;
#endif
@@ -162,17 +208,22 @@ class SimpleCPU : public BaseCPU
bool interval_stats;
#endif
- // L1 instruction cache
- MemInterface *icacheInterface;
-
- // L1 data cache
- MemInterface *dcacheInterface;
-
// current instruction
MachInst inst;
- // Refcounted pointer to the one memory request.
- MemReqPtr memReq;
+ // Static data storage
+ TheISA::IntReg dataReg;
+
+#if SIMPLE_CPU_MEM_TIMING
+ Packet *retry_pkt;
+#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
+ Request *ifetch_req;
+ Packet *ifetch_pkt;
+ Request *data_read_req;
+ Packet *data_read_pkt;
+ Request *data_write_req;
+ Packet *data_write_pkt;
+#endif
// Pointer to the sampler that is telling us to switchover.
// Used to signal the completion of the pipe drain and schedule
@@ -181,20 +232,6 @@ class SimpleCPU : public BaseCPU
StaticInstPtr curStaticInst;
- class CacheCompletionEvent : public Event
- {
- private:
- SimpleCPU *cpu;
-
- public:
- CacheCompletionEvent(SimpleCPU *_cpu);
-
- virtual void process();
- virtual const char *description();
- };
-
- CacheCompletionEvent cacheCompletionEvent;
-
Status status() const { return _status; }
virtual void activateContext(int thread_num, int delay);
@@ -227,15 +264,28 @@ class SimpleCPU : public BaseCPU
Stats::Average<> notIdleFraction;
Stats::Formula idleFraction;
- // number of cycles stalled for I-cache misses
+ // number of cycles stalled for I-cache responses
Stats::Scalar<> icacheStallCycles;
Counter lastIcacheStall;
- // number of cycles stalled for D-cache misses
+ // number of cycles stalled for I-cache retries
+ Stats::Scalar<> icacheRetryCycles;
+ Counter lastIcacheRetry;
+
+ // number of cycles stalled for D-cache responses
Stats::Scalar<> dcacheStallCycles;
Counter lastDcacheStall;
- void processCacheCompletion();
+ // number of cycles stalled for D-cache retries
+ Stats::Scalar<> dcacheRetryCycles;
+ Counter lastDcacheRetry;
+
+ void sendIcacheRequest(Packet *pkt);
+ void sendDcacheRequest(Packet *pkt);
+ void processResponse(Packet &response);
+
+ Packet * processRetry();
+ void recvStatusChange(Port::Status status) {}
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
@@ -281,22 +331,28 @@ class SimpleCPU : public BaseCPU
return cpuXC->readIntReg(si->srcRegIdx(idx));
}
- float readFloatRegSingle(const StaticInst *si, int idx)
+ FloatReg readFloatReg(const StaticInst *si, int idx, int width)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return cpuXC->readFloatReg(reg_idx, width);
+ }
+
+ FloatReg readFloatReg(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegSingle(reg_idx);
+ return cpuXC->readFloatReg(reg_idx);
}
- double readFloatRegDouble(const StaticInst *si, int idx)
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegDouble(reg_idx);
+ return cpuXC->readFloatRegBits(reg_idx, width);
}
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegInt(reg_idx);
+ return cpuXC->readFloatRegBits(reg_idx);
}
void setIntReg(const StaticInst *si, int idx, uint64_t val)
@@ -304,26 +360,38 @@ class SimpleCPU : public BaseCPU
cpuXC->setIntReg(si->destRegIdx(idx), val);
}
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegSingle(reg_idx, val);
+ cpuXC->setFloatReg(reg_idx, val, width);
}
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegDouble(reg_idx, val);
+ cpuXC->setFloatReg(reg_idx, val);
}
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
+ void setFloatRegBits(const StaticInst *si, int idx,
+ FloatRegBits val, int width)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegInt(reg_idx, val);
+ cpuXC->setFloatRegBits(reg_idx, val, width);
+ }
+
+ void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ cpuXC->setFloatRegBits(reg_idx, val);
}
uint64_t readPC() { return cpuXC->readPC(); }
+ uint64_t readNextPC() { return cpuXC->readNextPC(); }
+ uint64_t readNextNPC() { return cpuXC->readNextNPC(); }
+
+ void setPC(uint64_t val) { cpuXC->setPC(val); }
void setNextPC(uint64_t val) { cpuXC->setNextPC(val); }
+ void setNextNPC(uint64_t val) { cpuXC->setNextNPC(val); }
MiscReg readMiscReg(int misc_reg)
{
@@ -353,7 +421,7 @@ class SimpleCPU : public BaseCPU
void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
#else
- void syscall() { cpuXC->syscall(); }
+ void syscall(int64_t callnum) { cpuXC->syscall(callnum); }
#endif
bool misspeculating() { return cpuXC->misspeculating(); }
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 20116554e..f0b75c10e 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -33,8 +33,9 @@
#include <string>
#include "base/hashmap.hh"
+#include "base/misc.hh"
#include "base/refcnt.hh"
-#include "encumbered/cpu/full/op_class.hh"
+#include "cpu/op_class.hh"
#include "sim/host.hh"
#include "arch/isa_traits.hh"
@@ -390,6 +391,18 @@ class StaticInst : public StaticInstBase
/// @retval A pointer to the corresponding StaticInst object.
//This is defined as inline below.
static StaticInstPtr decode(ExtMachInst mach_inst);
+
+ //MIPS Decoder Debug Functions
+ int getOpcode() { return (machInst & 0xFC000000) >> 26 ; }//31..26
+ int getRs() { return (machInst & 0x03E00000) >> 21; } //25...21
+ int getRt() { return (machInst & 0x001F0000) >> 16; } //20...16
+ int getRd() { return (machInst & 0x0000F800) >> 11; } //15...11
+ int getImm() { return (machInst & 0x0000FFFF); } //15...0
+ int getFunction(){ return (machInst & 0x0000003F); }//5...0
+ int getBranch(){ return (machInst & 0x0000FFFF); }//15...0
+ int getJump(){ return (machInst & 0x03FFFFFF); }//5...0
+ int getHint(){ return (machInst & 0x000007C0) >> 6; } //10...6
+ std::string getName() { return mnemonic; }
};
typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 6ca5e3a06..2e46f7be1 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -41,36 +41,25 @@
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "dev/alpha_console.hh"
+#include "dev/platform.hh"
#include "dev/simconsole.hh"
#include "dev/simple_disk.hh"
-#include "dev/tsunami_io.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/physical.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
using namespace std;
using namespace AlphaISA;
-AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
- 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)
+AlphaConsole::AlphaConsole(Params *p)
+ : BasicPioDevice(p), disk(p->disk),
+ console(params()->cons), system(params()->alpha_sys), cpu(params()->cpu)
{
- mmu->add_child(this, RangeSize(addr, size));
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &AlphaConsole::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- }
+ pioSize = sizeof(struct AlphaAccess);
- alphaAccess = new Access;
- alphaAccess->last_offset = size - 1;
+ alphaAccess = new Access();
+ alphaAccess->last_offset = pioSize - 1;
alphaAccess->version = ALPHA_ACCESS_VERSION;
alphaAccess->diskUnit = 1;
@@ -83,130 +72,133 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
alphaAccess->inputChar = 0;
bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
- system->setAlphaAccess(addr);
}
void
AlphaConsole::startup()
{
+ system->setAlphaAccess(pioAddr);
alphaAccess->numCPUs = system->getNumCPUs();
alphaAccess->kernStart = system->getKernelStart();
alphaAccess->kernEnd = system->getKernelEnd();
alphaAccess->entryPoint = system->getKernelEntry();
alphaAccess->mem_size = system->physmem->size();
alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz
- alphaAccess->intrClockFrequency = platform->intrFrequency();
+ alphaAccess->intrClockFrequency = params()->platform->intrFrequency();
}
-Fault
-AlphaConsole::read(MemReqPtr &req, uint8_t *data)
+Tick
+AlphaConsole::read(Packet &pkt)
{
- memset(data, 0, req->size);
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
+ /** XXX Do we want to push the addr munging to a bus brige or something? So
+ * the device has it's physical address and then the bridge adds on whatever
+ * machine dependent address swizzle is required?
+ */
+
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
- switch (req->size)
+ pkt.time += pioDelay;
+ Addr daddr = pkt.addr - pioAddr;
+
+ pkt.allocate();
+
+ switch (pkt.size)
{
case sizeof(uint32_t):
- DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
- *(uint32_t*)data);
switch (daddr)
{
case offsetof(AlphaAccess, last_offset):
- *(uint32_t*)data = alphaAccess->last_offset;
+ pkt.set(alphaAccess->last_offset);
break;
case offsetof(AlphaAccess, version):
- *(uint32_t*)data = alphaAccess->version;
+ pkt.set(alphaAccess->version);
break;
case offsetof(AlphaAccess, numCPUs):
- *(uint32_t*)data = alphaAccess->numCPUs;
+ pkt.set(alphaAccess->numCPUs);
break;
case offsetof(AlphaAccess, intrClockFrequency):
- *(uint32_t*)data = alphaAccess->intrClockFrequency;
+ pkt.set(alphaAccess->intrClockFrequency);
break;
default:
- // Old console code read in everyting as a 32bit int
- *(uint32_t*)data = *(uint32_t*)(consoleData + daddr);
-
+ /* Old console code read in everyting as a 32bit int
+ * we now break that for better error checking.
+ */
+ pkt.result = BadAddress;
}
+ DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
+ pkt.get<uint32_t>());
break;
case sizeof(uint64_t):
- DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
- *(uint64_t*)data);
switch (daddr)
{
case offsetof(AlphaAccess, inputChar):
- *(uint64_t*)data = console->console_in();
+ pkt.set(console->console_in());
break;
case offsetof(AlphaAccess, cpuClock):
- *(uint64_t*)data = alphaAccess->cpuClock;
+ pkt.set(alphaAccess->cpuClock);
break;
case offsetof(AlphaAccess, mem_size):
- *(uint64_t*)data = alphaAccess->mem_size;
+ pkt.set(alphaAccess->mem_size);
break;
case offsetof(AlphaAccess, kernStart):
- *(uint64_t*)data = alphaAccess->kernStart;
+ pkt.set(alphaAccess->kernStart);
break;
case offsetof(AlphaAccess, kernEnd):
- *(uint64_t*)data = alphaAccess->kernEnd;
+ pkt.set(alphaAccess->kernEnd);
break;
case offsetof(AlphaAccess, entryPoint):
- *(uint64_t*)data = alphaAccess->entryPoint;
+ pkt.set(alphaAccess->entryPoint);
break;
case offsetof(AlphaAccess, diskUnit):
- *(uint64_t*)data = alphaAccess->diskUnit;
+ pkt.set(alphaAccess->diskUnit);
break;
case offsetof(AlphaAccess, diskCount):
- *(uint64_t*)data = alphaAccess->diskCount;
+ pkt.set(alphaAccess->diskCount);
break;
case offsetof(AlphaAccess, diskPAddr):
- *(uint64_t*)data = alphaAccess->diskPAddr;
+ pkt.set(alphaAccess->diskPAddr);
break;
case offsetof(AlphaAccess, diskBlock):
- *(uint64_t*)data = alphaAccess->diskBlock;
+ pkt.set(alphaAccess->diskBlock);
break;
case offsetof(AlphaAccess, diskOperation):
- *(uint64_t*)data = alphaAccess->diskOperation;
+ pkt.set(alphaAccess->diskOperation);
break;
case offsetof(AlphaAccess, outputChar):
- *(uint64_t*)data = alphaAccess->outputChar;
+ pkt.set(alphaAccess->outputChar);
break;
default:
int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
sizeof(alphaAccess->cpuStack[0]);
if (cpunum >= 0 && cpunum < 64)
- *(uint64_t*)data = alphaAccess->cpuStack[cpunum];
+ pkt.set(alphaAccess->cpuStack[cpunum]);
else
panic("Unknown 64bit access, %#x\n", daddr);
}
+ DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
+ pkt.get<uint64_t>());
break;
default:
- return genMachineCheckFault();
+ pkt.result = BadAddress;
}
-
- return NoFault;
+ if (pkt.result == Unknown) pkt.result = Success;
+ return pioDelay;
}
-Fault
-AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
+Tick
+AlphaConsole::write(Packet &pkt)
{
- uint64_t val;
-
- switch (req->size) {
- case sizeof(uint32_t):
- val = *(uint32_t *)data;
- break;
+ pkt.time += pioDelay;
- case sizeof(uint64_t):
- val = *(uint64_t *)data;
- break;
- default:
- return genMachineCheckFault();
- }
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ Addr daddr = pkt.addr - pioAddr;
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
- ExecContext *other_xc;
+ uint64_t val = pkt.get<uint64_t>();
+ assert(pkt.size == sizeof(uint64_t));
switch (daddr) {
case offsetof(AlphaAccess, diskUnit):
@@ -238,9 +230,6 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
console->out((char)(val & 0xff));
break;
- other_xc->activate(); //Start the cpu
- break;
-
default:
int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
sizeof(alphaAccess->cpuStack[0]);
@@ -252,13 +241,9 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
panic("Unknown 64bit access, %#x\n", daddr);
}
- return NoFault;
-}
+ pkt.result = Success;
-Tick
-AlphaConsole::cacheAccess(MemReqPtr &req)
-{
- return curTick + 1000;
+ return pioDelay;
}
void
@@ -321,14 +306,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
SimObjectParam<SimConsole *> sim_console;
SimObjectParam<SimpleDisk *> disk;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
+ Param<Addr> pio_addr;
SimObjectParam<AlphaSystem *> system;
SimObjectParam<BaseCPU *> cpu;
SimObjectParam<Platform *> platform;
- SimObjectParam<Bus*> pio_bus;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
@@ -336,21 +318,27 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
INIT_PARAM(sim_console, "The Simulator Console"),
INIT_PARAM(disk, "Simple Disk"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM(pio_addr, "Device Address"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu, "Processor"),
INIT_PARAM(platform, "platform"),
- INIT_PARAM(pio_bus, "The IO Bus to attach to"),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000)
END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
CREATE_SIM_OBJECT(AlphaConsole)
{
- return new AlphaConsole(getInstanceName(), sim_console, disk,
- system, cpu, platform, mmu, addr, hier, pio_bus);
+ AlphaConsole::Params *p = new AlphaConsole::Params;
+ p->name = getInstanceName();
+ p->platform = platform;
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->cons = sim_console;
+ p->disk = disk;
+ p->alpha_sys = system;
+ p->system = system;
+ p->cpu = cpu;
+ return new AlphaConsole(p);
}
REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index f63c6ad7e..05aec5ec1 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -43,7 +43,6 @@ class BaseCPU;
class SimConsole;
class AlphaSystem;
class SimpleDisk;
-class MemoryController;
/**
* Memory mapped interface to the system console. This device
@@ -70,7 +69,7 @@ class MemoryController;
* primarily used doing boot before the kernel has loaded its device
* drivers.
*/
-class AlphaConsole : public PioDevice
+class AlphaConsole : public BasicPioDevice
{
protected:
struct Access : public AlphaAccess
@@ -96,32 +95,35 @@ class AlphaConsole : public PioDevice
/** a pointer to the CPU boot cpu */
BaseCPU *cpu;
- Addr addr;
- static const Addr size = sizeof(struct AlphaAccess);
+ public:
+ struct Params : public BasicPioDevice::Params
+ {
+ SimConsole *cons;
+ SimpleDisk *disk;
+ AlphaSystem *alpha_sys;
+ BaseCPU *cpu;
+ };
+ protected:
+ const Params *params() const {return (const Params *)_params; }
public:
+
/** Standard Constructor */
- AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d,
- AlphaSystem *s, BaseCPU *c, Platform *platform,
- MemoryController *mmu, Addr addr,
- HierParams *hier, Bus *pio_bus);
+ AlphaConsole(Params *p);
virtual void startup();
/**
* memory mapped reads and writes
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
/**
* standard serialization routines for checkpointing
*/
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- public:
- Tick cacheAccess(MemReqPtr &req);
};
#endif // __ALPHA_CONSOLE_HH__
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 87d683a5d..dcabdbe0a 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -35,82 +35,63 @@
#include <vector>
#include "base/trace.hh"
-#include "cpu/exec_context.hh"
#include "dev/baddev.hh"
#include "dev/platform.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
+#include "mem/port.hh"
#include "sim/builder.hh"
#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)
- : PioDevice(name, NULL), addr(a), devname(devicename)
+BadDevice::BadDevice(Params *p)
+ : BasicPioDevice(p), devname(p->device_name)
{
- mmu->add_child(this, RangeSize(addr, size));
-
- if (pio_bus) {
- pioInterface = newPioInterface(name, hier, pio_bus, this,
- &BadDevice::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- }
-
+ pioSize = 0xf;
}
-Fault
-BadDevice::read(MemReqPtr &req, uint8_t *data)
-{
-
- panic("Device %s not imlpmented\n", devname);
- return NoFault;
-}
-
-Fault
-BadDevice::write(MemReqPtr &req, const uint8_t *data)
+Tick
+BadDevice::read(Packet &pkt)
{
panic("Device %s not imlpmented\n", devname);
- return NoFault;
}
Tick
-BadDevice::cacheAccess(MemReqPtr &req)
+BadDevice::write(Packet &pkt)
{
- return curTick;
+ panic("Device %s not imlpmented\n", devname);
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
+ Param<string> devicename;
+ Param<Addr> pio_addr;
+ SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<HierParams *> hier;
- SimObjectParam<Bus*> pio_bus;
Param<Tick> pio_latency;
- Param<string> devicename;
END_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice)
- INIT_PARAM(platform, "Platform"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
- INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
- INIT_PARAM(devicename, "Name of device to error on")
+ INIT_PARAM(devicename, "Name of device to error on"),
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(system, "system object"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000)
END_INIT_SIM_OBJECT_PARAMS(BadDevice)
CREATE_SIM_OBJECT(BadDevice)
{
- return new BadDevice(getInstanceName(), addr, mmu, hier, pio_bus,
- devicename);
+ BadDevice::Params *p = new BadDevice::Params;
+ p->name =getInstanceName();
+ p->platform = platform;
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->system = system;
+ p->device_name = devicename;
+ return new BadDevice(p);
}
REGISTER_SIM_OBJECT("BadDevice", BadDevice)
diff --git a/dev/baddev.hh b/dev/baddev.hh
index 189f28331..4cf0d6ba4 100644
--- a/dev/baddev.hh
+++ b/dev/baddev.hh
@@ -37,7 +37,6 @@
#include "base/range.hh"
#include "dev/io_device.hh"
-class MemoryController;
/**
* BadDevice
@@ -45,51 +44,29 @@ class MemoryController;
* the user that the kernel they are running has unsupported
* options (i.e. frame buffer)
*/
-class BadDevice : public PioDevice
+class BadDevice : public BasicPioDevice
{
private:
- Addr addr;
- static const Addr size = 0xf;
-
std::string devname;
public:
+ struct Params : public BasicPioDevice::Params
+ {
+ std::string device_name;
+ };
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ public:
/**
* Constructor for the Baddev Class.
- * @param name name of the object
+ * @param p object parameters
* @param a base address of the write
- * @param mmu the memory controller
- * @param hier object to store parameters universal the device hierarchy
- * @param bus The bus that this device is attached to
- * @param devicename device that is not implemented
- */
- BadDevice(const std::string &name, Addr a, MemoryController *mmu,
- HierParams *hier, Bus *bus, const std::string &devicename);
-
- /**
- * On a read event we just panic aand hopefully print a
- * meaningful error message.
- * @param req Contains the address to read from.
- * @param data A pointer to write the read data to.
- * @return The fault condition of the access.
- */
- virtual Fault read(MemReqPtr &req, uint8_t *data);
-
- /**
- * On a write event we just panic aand hopefully print a
- * meaningful error message.
- * @param req Contains the address to write to.
- * @param data The data to write.
- * @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ BadDevice(Params *p);
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
};
#endif // __DEV_BADDEV_HH__
diff --git a/dev/etherbus.cc b/dev/etherbus.cc
index c6b131e8e..906e324d3 100644
--- a/dev/etherbus.cc
+++ b/dev/etherbus.cc
@@ -81,7 +81,7 @@ EtherBus::reg(EtherInt *dev)
{ devlist.push_back(dev); }
bool
-EtherBus::send(EtherInt *sndr, PacketPtr &pkt)
+EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt)
{
if (busy()) {
DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick);
diff --git a/dev/etherbus.hh b/dev/etherbus.hh
index ca859d85f..4a364abd8 100644
--- a/dev/etherbus.hh
+++ b/dev/etherbus.hh
@@ -61,7 +61,7 @@ class EtherBus : public SimObject
};
DoneEvent event;
- PacketPtr packet;
+ EthPacketPtr packet;
EtherInt *sender;
EtherDump *dump;
@@ -73,7 +73,7 @@ class EtherBus : public SimObject
void txDone();
void reg(EtherInt *dev);
bool busy() const { return (bool)packet; }
- bool send(EtherInt *sender, PacketPtr &packet);
+ bool send(EtherInt *sender, EthPacketPtr &packet);
};
#endif // __ETHERBUS_H__
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index d8a51fc5b..cb5f0b70e 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -102,7 +102,7 @@ EtherDump::init()
}
void
-EtherDump::dumpPacket(PacketPtr &packet)
+EtherDump::dumpPacket(EthPacketPtr &packet)
{
pcap_pkthdr pkthdr;
pkthdr.seconds = curtime + (curTick / Clock::Int::s);
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
index 149192cd7..8bba073fe 100644
--- a/dev/etherdump.hh
+++ b/dev/etherdump.hh
@@ -45,7 +45,7 @@ class EtherDump : public SimObject
private:
std::ofstream stream;
const int maxlen;
- void dumpPacket(PacketPtr &packet);
+ void dumpPacket(EthPacketPtr &packet);
void init();
Tick curtime;
@@ -53,7 +53,7 @@ class EtherDump : public SimObject
public:
EtherDump(const std::string &name, const std::string &file, int max);
- inline void dump(PacketPtr &pkt) { dumpPacket(pkt); }
+ inline void dump(EthPacketPtr &pkt) { dumpPacket(pkt); }
};
#endif // __ETHERDUMP_H__
diff --git a/dev/etherint.hh b/dev/etherint.hh
index e397846ae..1f641fadb 100644
--- a/dev/etherint.hh
+++ b/dev/etherint.hh
@@ -58,9 +58,9 @@ class EtherInt : public SimObject
void recvDone() { peer->sendDone(); }
virtual void sendDone() = 0;
- bool sendPacket(PacketPtr packet)
+ bool sendPacket(EthPacketPtr packet)
{ return peer ? peer->recvPacket(packet) : true; }
- virtual bool recvPacket(PacketPtr packet) = 0;
+ virtual bool recvPacket(EthPacketPtr packet) = 0;
};
#endif // __DEV_ETHERINT_HH__
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index f68332926..5b6531c2e 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -102,7 +102,7 @@ EtherLink::unserialize(Checkpoint *cp, const string &section)
}
void
-EtherLink::Link::txComplete(PacketPtr packet)
+EtherLink::Link::txComplete(EthPacketPtr packet)
{
DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
DDUMP(EthernetData, packet->data, packet->length);
@@ -113,12 +113,12 @@ class LinkDelayEvent : public Event
{
protected:
EtherLink::Link *link;
- PacketPtr packet;
+ EthPacketPtr packet;
public:
// non-scheduling version for createForUnserialize()
LinkDelayEvent();
- LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when);
+ LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when);
void process();
@@ -148,7 +148,7 @@ EtherLink::Link::txDone()
}
bool
-EtherLink::Link::transmit(PacketPtr pkt)
+EtherLink::Link::transmit(EthPacketPtr pkt)
{
if (busy()) {
DPRINTF(Ethernet, "packet not sent, link busy\n");
@@ -195,7 +195,7 @@ EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
bool packet_exists;
paramIn(cp, section, base + ".packet_exists", packet_exists);
if (packet_exists) {
- packet = new PacketData(16384);
+ packet = new EthPacketData(16384);
packet->unserialize(base + ".packet", cp, section);
}
@@ -215,7 +215,7 @@ LinkDelayEvent::LinkDelayEvent()
setFlags(AutoDelete);
}
-LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when)
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when)
: Event(&mainEventQueue), link(l), packet(p)
{
setFlags(AutoSerialize);
@@ -256,7 +256,7 @@ LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
link = parent->link[number];
- packet = new PacketData(16384);
+ packet = new EthPacketData(16384);
packet->unserialize("packet", cp, section);
}
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index 305007d9e..570444e1b 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -73,14 +73,14 @@ class EtherLink : public SimObject
/*
* Transfer is complete
*/
- PacketPtr packet;
+ EthPacketPtr packet;
void txDone();
typedef EventWrapper<Link, &Link::txDone> DoneEvent;
friend void DoneEvent::process();
DoneEvent doneEvent;
friend class LinkDelayEvent;
- void txComplete(PacketPtr packet);
+ void txComplete(EthPacketPtr packet);
public:
Link(const std::string &name, EtherLink *p, int num,
@@ -90,7 +90,7 @@ class EtherLink : public SimObject
const std::string name() const { return objName; }
bool busy() const { return (bool)packet; }
- bool transmit(PacketPtr packet);
+ bool transmit(EthPacketPtr packet);
void setTxInt(Interface *i) { assert(!txint); txint = i; }
void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
@@ -110,7 +110,7 @@ class EtherLink : public SimObject
public:
Interface(const std::string &name, Link *txlink, Link *rxlink);
- bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); }
+ bool recvPacket(EthPacketPtr packet) { return txlink->transmit(packet); }
void sendDone() { peer->sendDone(); }
};
diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc
index 44dbd7c18..85e18e981 100644
--- a/dev/etherpkt.cc
+++ b/dev/etherpkt.cc
@@ -35,7 +35,7 @@
using namespace std;
void
-PacketData::serialize(const string &base, ostream &os)
+EthPacketData::serialize(const string &base, ostream &os)
{
paramOut(os, base + ".length", length);
paramOut(os, base + ".slack", slack);
@@ -43,7 +43,7 @@ PacketData::serialize(const string &base, ostream &os)
}
void
-PacketData::unserialize(const string &base, Checkpoint *cp,
+EthPacketData::unserialize(const string &base, Checkpoint *cp,
const string &section)
{
paramIn(cp, section, base + ".length", length);
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
index cb9022d72..01741b3d5 100644
--- a/dev/etherpkt.hh
+++ b/dev/etherpkt.hh
@@ -44,7 +44,7 @@
* Reference counted class containing ethernet packet data
*/
class Checkpoint;
-class PacketData : public RefCounted
+class EthPacketData : public RefCounted
{
public:
/*
@@ -66,12 +66,12 @@ class PacketData : public RefCounted
int slack;
public:
- PacketData() : data(NULL), length(0), slack(0) { }
- explicit PacketData(size_t size)
+ EthPacketData() : data(NULL), length(0), slack(0) { }
+ explicit EthPacketData(size_t size)
: data(new uint8_t[size]), length(0), slack(0) { }
- PacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
+ EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
: data(d.release()), length(l), slack(s) { }
- ~PacketData() { if (data) delete [] data; }
+ ~EthPacketData() { if (data) delete [] data; }
public:
void serialize(const std::string &base, std::ostream &os);
@@ -79,6 +79,6 @@ class PacketData : public RefCounted
const std::string &section);
};
-typedef RefCountingPtr<PacketData> PacketPtr;
+typedef RefCountingPtr<EthPacketData> EthPacketPtr;
#endif // __ETHERPKT_HH__
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index 7589991ef..b5abb1d62 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -169,7 +169,7 @@ EtherTap::detach()
}
bool
-EtherTap::recvPacket(PacketPtr packet)
+EtherTap::recvPacket(EthPacketPtr packet)
{
if (dump)
dump->dump(packet);
@@ -218,8 +218,8 @@ EtherTap::process(int revent)
}
while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
- PacketPtr packet;
- packet = new PacketData(data_len);
+ EthPacketPtr packet;
+ packet = new EthPacketData(data_len);
packet->length = data_len;
memcpy(packet->data, data, data_len);
@@ -250,7 +250,7 @@ EtherTap::retransmit()
if (packetBuffer.empty())
return;
- PacketPtr packet = packetBuffer.front();
+ EthPacketPtr packet = packetBuffer.front();
if (sendPacket(packet)) {
if (dump)
dump->dump(packet);
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
index 069ba734f..40ce6af0b 100644
--- a/dev/ethertap.hh
+++ b/dev/ethertap.hh
@@ -70,10 +70,10 @@ class EtherTap : public EtherInt
protected:
std::string device;
- std::queue<PacketPtr> packetBuffer;
+ std::queue<EthPacketPtr> packetBuffer;
void process(int revent);
- void enqueue(PacketData *packet);
+ void enqueue(EthPacketData *packet);
void retransmit();
/*
@@ -97,7 +97,7 @@ class EtherTap : public EtherInt
EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz);
virtual ~EtherTap();
- virtual bool recvPacket(PacketPtr packet);
+ virtual bool recvPacket(EthPacketPtr packet);
virtual void sendDone();
virtual void serialize(std::ostream &os);
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index 05c756f04..abdbe5d0a 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -38,17 +38,12 @@
#include "dev/pciconfigall.hh"
#include "dev/pcireg.h"
#include "dev/platform.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/dma_interface.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
+#include "sim/byteswap.hh"
using namespace std;
-using namespace TheISA;
////
// Initialization and destruction
@@ -91,22 +86,6 @@ IdeController::IdeController(Params *p)
bm_enabled = false;
memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
- pioInterface = NULL;
- dmaInterface = NULL;
- // create the PIO and DMA interfaces
- if (params()->pio_bus) {
- pioInterface = newPioInterface(name() + ".pio", params()->hier,
- params()->pio_bus, this,
- &IdeController::cacheAccess);
- pioLatency = params()->pio_latency * params()->pio_bus->clockRate;
- }
-
- if (params()->dma_bus) {
- dmaInterface = new DMAInterface<Bus>(name() + ".dma",
- params()->dma_bus,
- params()->dma_bus, 1, true);
- }
-
// setup the disks attached to controller
memset(disks, 0, sizeof(disks));
dev[0] = 0;
@@ -117,7 +96,7 @@ IdeController::IdeController(Params *p)
for (int i = 0; i < params()->disks.size(); i++) {
disks[i] = params()->disks[i];
- disks[i]->setController(this, dmaInterface);
+ disks[i]->setController(this);
}
}
@@ -239,121 +218,158 @@ IdeController::setDmaComplete(IdeDisk *disk)
}
}
-////
-// Bus timing and bus access functions
-////
-
-Tick
-IdeController::cacheAccess(MemReqPtr &req)
-{
- // @todo Add more accurate timing to cache access
- return curTick + pioLatency;
-}
////
// Read and write handling
////
void
-IdeController::readConfig(int offset, int size, uint8_t *data)
+IdeController::readConfig(int offset, uint8_t *data)
{
- int config_offset;
-
if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::readConfig(offset, size, data);
+ PciDev::readConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
- (offset + size) <= IDE_CTRL_CONF_END) {
+ (offset + 1) <= IDE_CTRL_CONF_END) {
- config_offset = offset - IDE_CTRL_CONF_START;
-
- switch (size) {
- case sizeof(uint8_t):
- *data = config_regs.data[config_offset];
+ switch (offset) {
+ case IDE_CTRL_CONF_DEV_TIMING:
+ *data = config_regs.sidetim;
break;
- case sizeof(uint16_t):
- *(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset];
+ case IDE_CTRL_CONF_UDMA_CNTRL:
+ *data = config_regs.udmactl;
break;
- case sizeof(uint32_t):
- *(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset];
+ case IDE_CTRL_CONF_PRIM_TIMING+1:
+ *data = htole(config_regs.idetim0) >> 8;
+ break;
+ case IDE_CTRL_CONF_SEC_TIMING+1:
+ *data = htole(config_regs.idetim1) >> 8;
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG:
+ *data = htole(config_regs.ideconfig) & 0xFF;
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG+1:
+ *data = htole(config_regs.ideconfig) >> 8;
break;
default:
- panic("Invalid PCI configuration read size!\n");
+ panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
+ offset);
}
-
-
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
- switch (size) {
- case sizeof(uint8_t):
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n",
- offset, size, (uint32_t)*data);
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n",
+ offset, (uint32_t)*data);
+}
+
+void
+IdeController::readConfig(int offset, uint16_t *data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC) {
+ PciDev::readConfig(offset, data);
+ } else if (offset >= IDE_CTRL_CONF_START &&
+ (offset + 2) <= IDE_CTRL_CONF_END) {
+
+ switch (offset) {
+ case IDE_CTRL_CONF_PRIM_TIMING:
+ *data = config_regs.idetim0;
break;
- case sizeof(uint16_t):
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n",
- offset, size, *(uint16_t*)data);
+ case IDE_CTRL_CONF_SEC_TIMING:
+ *data = config_regs.idetim1;
break;
- case sizeof(uint32_t):
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n",
- offset, size, *(uint32_t*)data);
+ case IDE_CTRL_CONF_UDMA_TIMING:
+ *data = config_regs.udmatim;
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG:
+ *data = config_regs.ideconfig;
break;
default:
- panic("Invalid PCI configuration read size!\n");
+ panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
+ offset);
}
+ } else {
+ panic("Read of unimplemented PCI config. register: %x\n", offset);
+ }
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data);
}
void
-IdeController::writeConfig(int offset, int size, const uint8_t *data)
+IdeController::readConfig(int offset, uint32_t *data)
{
- int config_offset;
-
if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::writeConfig(offset, size, data);
+ PciDev::readConfig(offset, data);
+ } else {
+ panic("Read of unimplemented PCI config. register: %x\n", offset);
+ }
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data);
+}
+void
+IdeController::writeConfig(int offset, const uint8_t data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC) {
+ PciDev::writeConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
- (offset + size) <= IDE_CTRL_CONF_END) {
+ (offset + 1) <= IDE_CTRL_CONF_END) {
- config_offset = offset - IDE_CTRL_CONF_START;
-
- switch(size) {
- case sizeof(uint8_t):
- config_regs.data[config_offset] = *data;
+ switch (offset) {
+ case IDE_CTRL_CONF_DEV_TIMING:
+ config_regs.sidetim = data;
break;
- case sizeof(uint16_t):
- *(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data;
+ case IDE_CTRL_CONF_UDMA_CNTRL:
+ config_regs.udmactl = data;
break;
- case sizeof(uint32_t):
- *(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data;
+ case IDE_CTRL_CONF_IDE_CONFIG:
+ config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data);
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG+1:
+ config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8;
break;
default:
- panic("Invalid PCI configuration write size!\n");
+ panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
+ offset);
}
+
} else {
- panic("Write of unimplemented PCI config. register: %x\n", offset);
+ panic("Read of unimplemented PCI config. register: %x\n", offset);
}
+ DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
+ offset, (uint32_t)data);
+}
- switch(size) {
- case sizeof(uint8_t):
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
- offset, size, (uint32_t)*data);
+void
+IdeController::writeConfig(int offset, const uint16_t data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC) {
+ PciDev::writeConfig(offset, data);
+ } else if (offset >= IDE_CTRL_CONF_START &&
+ (offset + 2) <= IDE_CTRL_CONF_END) {
+
+ switch (offset) {
+ case IDE_CTRL_CONF_PRIM_TIMING:
+ config_regs.idetim0 = data;
break;
- case sizeof(uint16_t):
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
- offset, size, *(uint16_t*)data);
+ case IDE_CTRL_CONF_SEC_TIMING:
+ config_regs.idetim1 = data;
break;
- case sizeof(uint32_t):
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
- offset, size, *(uint32_t*)data);
+ case IDE_CTRL_CONF_UDMA_TIMING:
+ config_regs.udmatim = data;
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG:
+ config_regs.ideconfig = data;
break;
default:
- panic("Invalid PCI configuration write size!\n");
+ panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
+ offset);
}
- // Catch the writes to specific PCI registers that have side affects
- // (like updating the PIO ranges)
- switch (offset) {
- case PCI_COMMAND:
+ } else {
+ panic("Write of unimplemented PCI config. register: %x\n", offset);
+ }
+ DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data);
+
+ /* Trap command register writes and enable IO/BM as appropriate. */
+ if (offset == PCI_COMMAND) {
if (letoh(config.command) & PCI_CMD_IOSE)
io_enabled = true;
else
@@ -363,91 +379,83 @@ IdeController::writeConfig(int offset, int size, const uint8_t *data)
bm_enabled = true;
else
bm_enabled = false;
- break;
+ }
+
+}
+
+void
+IdeController::writeConfig(int offset, const uint32_t data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC) {
+ PciDev::writeConfig(offset, data);
+ } else {
+ panic("Read of unimplemented PCI config. register: %x\n", offset);
+ }
+
+ DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data);
+ switch(offset) {
case PCI0_BASE_ADDR0:
- if (BARAddrs[0] != 0) {
+ if (BARAddrs[0] != 0)
pri_cmd_addr = BARAddrs[0];
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(pri_cmd_addr,
- pri_cmd_size));
-
- pri_cmd_addr &= EV5::PAddrUncachedMask;
- }
break;
case PCI0_BASE_ADDR1:
- if (BARAddrs[1] != 0) {
+ if (BARAddrs[1] != 0)
pri_ctrl_addr = BARAddrs[1];
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(pri_ctrl_addr,
- pri_ctrl_size));
-
- pri_ctrl_addr &= EV5::PAddrUncachedMask;
- }
break;
case PCI0_BASE_ADDR2:
- if (BARAddrs[2] != 0) {
+ if (BARAddrs[2] != 0)
sec_cmd_addr = BARAddrs[2];
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(sec_cmd_addr,
- sec_cmd_size));
-
- sec_cmd_addr &= EV5::PAddrUncachedMask;
- }
break;
case PCI0_BASE_ADDR3:
- if (BARAddrs[3] != 0) {
+ if (BARAddrs[3] != 0)
sec_ctrl_addr = BARAddrs[3];
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(sec_ctrl_addr,
- sec_ctrl_size));
-
- sec_ctrl_addr &= EV5::PAddrUncachedMask;
- }
break;
case PCI0_BASE_ADDR4:
- if (BARAddrs[4] != 0) {
+ if (BARAddrs[4] != 0)
bmi_addr = BARAddrs[4];
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
-
- bmi_addr &= EV5::PAddrUncachedMask;
- }
break;
}
}
-Fault
-IdeController::read(MemReqPtr &req, uint8_t *data)
+Tick
+IdeController::read(Packet &pkt)
{
Addr offset;
IdeChannel channel;
IdeRegType reg_type;
int disk;
- parseAddr(req->paddr, offset, channel, reg_type);
+ pkt.time += pioDelay;
+ pkt.allocate();
+ if (pkt.size != 1 && pkt.size != 2 && pkt.size !=4)
+ panic("Bad IDE read size: %d\n", pkt.size);
+
+ parseAddr(pkt.addr, offset, channel, reg_type);
- if (!io_enabled)
- return NoFault;
+ if (!io_enabled) {
+ pkt.result = Success;
+ return pioDelay;
+ }
switch (reg_type) {
case BMI_BLOCK:
- switch (req->size) {
+ switch (pkt.size) {
case sizeof(uint8_t):
- *data = bmi_regs.data[offset];
+ pkt.set(bmi_regs.data[offset]);
break;
case sizeof(uint16_t):
- *(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset];
+ pkt.set(*(uint16_t*)&bmi_regs.data[offset]);
break;
case sizeof(uint32_t):
- *(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset];
+ pkt.set(*(uint32_t*)&bmi_regs.data[offset]);
break;
default:
- panic("IDE read of BMI reg invalid size: %#x\n", req->size);
+ panic("IDE read of BMI reg invalid size: %#x\n", pkt.size);
}
break;
@@ -455,51 +463,54 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
case CONTROL_BLOCK:
disk = getDisk(channel);
- if (disks[disk] == NULL)
+ if (disks[disk] == NULL) {
+ pkt.set<uint8_t>(0);
break;
+ }
switch (offset) {
case DATA_OFFSET:
- switch (req->size) {
+ switch (pkt.size) {
case sizeof(uint16_t):
- disks[disk]->read(offset, reg_type, data);
+ disks[disk]->read(offset, reg_type, pkt.getPtr<uint8_t>());
break;
case sizeof(uint32_t):
- disks[disk]->read(offset, reg_type, data);
- disks[disk]->read(offset, reg_type, &data[2]);
+ disks[disk]->read(offset, reg_type, pkt.getPtr<uint8_t>());
+ disks[disk]->read(offset, reg_type,
+ pkt.getPtr<uint8_t>() + sizeof(uint16_t));
break;
default:
- panic("IDE read of data reg invalid size: %#x\n", req->size);
+ panic("IDE read of data reg invalid size: %#x\n", pkt.size);
}
break;
default:
- if (req->size == sizeof(uint8_t)) {
- disks[disk]->read(offset, reg_type, data);
+ if (pkt.size == sizeof(uint8_t)) {
+ disks[disk]->read(offset, reg_type, pkt.getPtr<uint8_t>());
} else
- panic("IDE read of command reg of invalid size: %#x\n", req->size);
+ panic("IDE read of command reg of invalid size: %#x\n", pkt.size);
}
break;
default:
panic("IDE controller read of unknown register block type!\n");
}
-
- if (req->size == 1)
+ if (pkt.size == 1)
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size, (uint32_t)*data);
- else if (req->size == 2)
+ offset, pkt.size, (uint32_t)pkt.get<uint8_t>());
+ else if (pkt.size == 2)
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint16_t*)data);
+ offset, pkt.size, pkt.get<uint16_t>());
else
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint32_t*)data);
+ offset, pkt.size, pkt.get<uint32_t>());
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
-Fault
-IdeController::write(MemReqPtr &req, const uint8_t *data)
+Tick
+IdeController::write(Packet &pkt)
{
Addr offset;
IdeChannel channel;
@@ -507,28 +518,35 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
int disk;
uint8_t oldVal, newVal;
- parseAddr(req->paddr, offset, channel, reg_type);
+ pkt.time += pioDelay;
- if (!io_enabled)
- return NoFault;
+ parseAddr(pkt.addr, offset, channel, reg_type);
+
+ if (!io_enabled) {
+ pkt.result = Success;
+ DPRINTF(IdeCtrl, "io not enabled\n");
+ return pioDelay;
+ }
switch (reg_type) {
case BMI_BLOCK:
- if (!bm_enabled)
- return NoFault;
+ if (!bm_enabled) {
+ pkt.result = Success;
+ return pioDelay;
+ }
switch (offset) {
// Bus master IDE command register
case BMIC1:
case BMIC0:
- if (req->size != sizeof(uint8_t))
- panic("Invalid BMIC write size: %x\n", req->size);
+ if (pkt.size != sizeof(uint8_t))
+ panic("Invalid BMIC write size: %x\n", pkt.size);
// select the current disk based on DEV bit
disk = getDisk(channel);
oldVal = bmi_regs.chan[channel].bmic;
- newVal = *data;
+ newVal = pkt.get<uint8_t>();
// if a DMA transfer is in progress, R/W control cannot change
if (oldVal & SSBM) {
@@ -577,11 +595,11 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
// Bus master IDE status register
case BMIS0:
case BMIS1:
- if (req->size != sizeof(uint8_t))
- panic("Invalid BMIS write size: %x\n", req->size);
+ if (pkt.size != sizeof(uint8_t))
+ panic("Invalid BMIS write size: %x\n", pkt.size);
oldVal = bmi_regs.chan[channel].bmis;
- newVal = *data;
+ newVal = pkt.get<uint8_t>();
// the BMIDEA bit is RO
newVal |= (oldVal & BMIDEA);
@@ -604,30 +622,28 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
case BMIDTP0:
case BMIDTP1:
{
- if (req->size != sizeof(uint32_t))
- panic("Invalid BMIDTP write size: %x\n", req->size);
+ if (pkt.size != sizeof(uint32_t))
+ panic("Invalid BMIDTP write size: %x\n", pkt.size);
- uint32_t host_data = letoh(*(uint32_t*)data);
- host_data &= ~0x3;
- bmi_regs.chan[channel].bmidtp = htole(host_data);
+ bmi_regs.chan[channel].bmidtp = htole(pkt.get<uint32_t>() & ~0x3);
}
break;
default:
- if (req->size != sizeof(uint8_t) &&
- req->size != sizeof(uint16_t) &&
- req->size != sizeof(uint32_t))
+ if (pkt.size != sizeof(uint8_t) &&
+ pkt.size != sizeof(uint16_t) &&
+ pkt.size != sizeof(uint32_t))
panic("IDE controller write of invalid write size: %x\n",
- req->size);
+ pkt.size);
// do a default copy of data into the registers
- memcpy(&bmi_regs.data[offset], data, req->size);
+ memcpy(&bmi_regs.data[offset], pkt.getPtr<uint8_t>(), pkt.size);
}
break;
case COMMAND_BLOCK:
if (offset == IDE_SELECT_OFFSET) {
uint8_t *devBit = &dev[channel];
- *devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0;
+ *devBit = (letoh(pkt.get<uint8_t>()) & IDE_SELECT_DEV_BIT) ? 1 : 0;
}
// fall-through ok!
case CONTROL_BLOCK:
@@ -638,40 +654,44 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
switch (offset) {
case DATA_OFFSET:
- switch (req->size) {
+ switch (pkt.size) {
case sizeof(uint16_t):
- disks[disk]->write(offset, reg_type, data);
+ disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>());
break;
case sizeof(uint32_t):
- disks[disk]->write(offset, reg_type, data);
- disks[disk]->write(offset, reg_type, &data[2]);
+ disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>());
+ disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>() +
+ sizeof(uint16_t));
break;
default:
- panic("IDE write of data reg invalid size: %#x\n", req->size);
+ panic("IDE write of data reg invalid size: %#x\n", pkt.size);
}
break;
default:
- if (req->size == sizeof(uint8_t)) {
- disks[disk]->write(offset, reg_type, data);
+ if (pkt.size == sizeof(uint8_t)) {
+ disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>());
} else
- panic("IDE write of command reg of invalid size: %#x\n", req->size);
+ panic("IDE write of command reg of invalid size: %#x\n", pkt.size);
}
break;
default:
panic("IDE controller write of unknown register block type!\n");
}
- if (req->size == 1)
+
+ if (pkt.size == 1)
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size, (uint32_t)*data);
- else if (req->size == 2)
+ offset, pkt.size, (uint32_t)pkt.get<uint8_t>());
+ else if (pkt.size == 2)
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint16_t*)data);
+ offset, pkt.size, pkt.get<uint16_t>());
else
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint32_t*)data);
+ offset, pkt.size, pkt.get<uint32_t>());
- return NoFault;
+
+ pkt.result = Success;
+ return pioDelay;
}
////
@@ -740,51 +760,36 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(bm_enabled);
UNSERIALIZE_ARRAY(cmd_in_progress,
sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
-
- if (pioInterface) {
- pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size));
- pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size));
- pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size));
- pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size));
- pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
- }
+ pioPort->sendStatusChange(Port::RangeChange);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
- Param<Addr> addr;
- SimObjectVectorParam<IdeDisk *> disks;
- SimObjectParam<MemoryController *> mmu;
+ SimObjectParam<System *> system;
+ SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
- SimObjectParam<Bus *> pio_bus;
- SimObjectParam<Bus *> dma_bus;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
+ SimObjectVectorParam<IdeDisk *> disks;
END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM(disks, "IDE disks attached to this controller"),
- INIT_PARAM(mmu, "Memory controller"),
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
- INIT_PARAM(pio_bus, ""),
- INIT_PARAM(dma_bus, ""),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+ INIT_PARAM(disks, "IDE disks attached to this controller")
END_INIT_SIM_OBJECT_PARAMS(IdeController)
@@ -792,19 +797,15 @@ CREATE_SIM_OBJECT(IdeController)
{
IdeController::Params *params = new IdeController::Params;
params->name = getInstanceName();
- params->mmu = mmu;
+ params->platform = platform;
+ params->system = system;
params->configSpace = configspace;
params->configData = configdata;
- params->plat = platform;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
params->functionNum = pci_func;
-
+ params->pio_delay = pio_latency;
params->disks = disks;
- params->pio_bus = pio_bus;
- params->dma_bus = dma_bus;
- params->pio_latency = pio_latency;
- params->hier = hier;
return new IdeController(params);
}
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index 0fbaf9207..a074f4f97 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -70,6 +70,13 @@
#define IDE_CTRL_CONF_START 0x40
#define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs))
+#define IDE_CTRL_CONF_PRIM_TIMING 0x40
+#define IDE_CTRL_CONF_SEC_TIMING 0x42
+#define IDE_CTRL_CONF_DEV_TIMING 0x44
+#define IDE_CTRL_CONF_UDMA_CNTRL 0x48
+#define IDE_CTRL_CONF_UDMA_TIMING 0x4A
+#define IDE_CTRL_CONF_IDE_CONFIG 0x54
+
enum IdeRegType {
COMMAND_BLOCK,
@@ -77,13 +84,9 @@ enum IdeRegType {
BMI_BLOCK
};
-class BaseInterface;
-class Bus;
-class HierParams;
class IdeDisk;
class IntrControl;
class PciConfigAll;
-class PhysicalMemory;
class Platform;
/**
@@ -191,10 +194,6 @@ class IdeController : public PciDev
{
/** Array of disk objects */
std::vector<IdeDisk *> disks;
- Bus *pio_bus;
- Bus *dma_bus;
- Tick pio_latency;
- HierParams *hier;
};
const Params *params() const { return (const Params *)_params; }
@@ -202,26 +201,28 @@ class IdeController : public PciDev
IdeController(Params *p);
~IdeController();
- virtual void writeConfig(int offset, int size, const uint8_t *data);
- virtual void readConfig(int offset, int size, uint8_t *data);
+ virtual void writeConfig(int offset, const uint8_t data);
+ virtual void writeConfig(int offset, const uint16_t data);
+ virtual void writeConfig(int offset, const uint32_t data);
+ virtual void readConfig(int offset, uint8_t *data);
+ virtual void readConfig(int offset, uint16_t *data);
+ virtual void readConfig(int offset, uint32_t *data);
void setDmaComplete(IdeDisk *disk);
/**
* Read a done field for a given target.
- * @param req Contains the address of the field to read.
- * @param data Return the field read.
- * @return The fault condition of the access.
+ * @param pkt Packet describing what is to be read
+ * @return The amount of time to complete this request
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Tick read(Packet &pkt);
/**
- * Write to the mmapped I/O control registers.
- * @param req Contains the address to write to.
- * @param data The data to write.
- * @return The fault condition of the access.
+ * Write a done field for a given target.
+ * @param pkt Packet describing what is to be written
+ * @return The amount of time to complete this request
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick write(Packet &pkt);
/**
* Serialize this object to the given output stream.
@@ -236,11 +237,5 @@ class IdeController : public PciDev
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
};
#endif // __IDE_CTRL_HH_
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index c13556ed6..6f4234a1d 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -35,6 +35,7 @@
#include <deque>
#include <string>
+#include "base/chunk_generator.hh"
#include "base/cprintf.hh" // csprintf
#include "base/trace.hh"
#include "dev/disk_image.hh"
@@ -42,11 +43,6 @@
#include "dev/ide_ctrl.hh"
#include "dev/tsunami.hh"
#include "dev/tsunami_pchip.hh"
-#include "mem/functional/physical.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/dma_interface.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
#include "sim/root.hh"
@@ -55,11 +51,11 @@
using namespace std;
using namespace TheISA;
-IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
+IdeDisk::IdeDisk(const string &name, DiskImage *img,
int id, Tick delay)
- : SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay),
- dmaTransferEvent(this), dmaReadWaitEvent(this),
- dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
+ : SimObject(name), ctrl(NULL), image(img), diskDelay(delay),
+ dmaTransferEvent(this), dmaReadCG(NULL), dmaReadWaitEvent(this),
+ dmaWriteCG(NULL), dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this)
{
// Reset the device state
@@ -139,7 +135,6 @@ IdeDisk::reset(int id)
memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
- dmaInterfaceBytes = 0;
curPrdAddr = 0;
curSector = 0;
cmdBytes = 0;
@@ -188,29 +183,6 @@ IdeDisk::pciToDma(Addr pciAddr)
panic("Access to unset controller!\n");
}
-uint32_t
-IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
-{
- uint32_t bytesInPage = 0;
-
- // First calculate how many bytes could be in the page
- if (bytesLeft > TheISA::PageBytes)
- bytesInPage = TheISA::PageBytes;
- else
- bytesInPage = bytesLeft;
-
- // Next, see if we have crossed a page boundary, and adjust
- Addr upperBound = curAddr + bytesInPage;
- Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes;
-
- assert(upperBound >= curAddr && "DMA read wraps around address space!\n");
-
- if (upperBound >= pageBound)
- bytesInPage = pageBound - curAddr;
-
- return bytesInPage;
-}
-
////
// Device registers read/write
////
@@ -263,6 +235,8 @@ IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data)
default:
panic("Unknown register block!\n");
}
+ DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset,
+ (uint32_t)*data);
if (action != ACT_NONE)
updateState(action);
@@ -324,6 +298,8 @@ IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data)
panic("Unknown register block!\n");
}
+ DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset,
+ (uint32_t)*data);
if (action != ACT_NONE)
updateState(action);
}
@@ -339,29 +315,17 @@ IdeDisk::doDmaTransfer()
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState);
- // first read the current PRD
- if (dmaInterface) {
- if (dmaInterface->busy()) {
- // reschedule after waiting period
- dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
- return;
- }
-
- dmaInterface->doDMA(Read, curPrdAddr, sizeof(PrdEntry_t), curTick,
- &dmaPrdReadEvent);
- } else {
- dmaPrdReadDone();
- }
+ if (ctrl->dmaPending()) {
+ dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+ return;
+ } else
+ ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent,
+ (uint8_t*)&curPrd.entry);
}
void
IdeDisk::dmaPrdReadDone()
{
- // actually copy the PRD from physical memory
- memcpy((void *)&curPrd.entry,
- physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)),
- sizeof(PrdEntry_t));
-
DPRINTF(IdeDisk,
"PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
@@ -372,73 +336,49 @@ IdeDisk::dmaPrdReadDone()
curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
if (dmaRead)
- doDmaRead();
+ doDmaDataRead();
else
- doDmaWrite();
+ doDmaDataWrite();
}
void
-IdeDisk::regStats()
-{
- using namespace Stats;
- dmaReadFullPages
- .name(name() + ".dma_read_full_pages")
- .desc("Number of full page size DMA reads (not PRD).")
- ;
- dmaReadBytes
- .name(name() + ".dma_read_bytes")
- .desc("Number of bytes transfered via DMA reads (not PRD).")
- ;
- dmaReadTxs
- .name(name() + ".dma_read_txs")
- .desc("Number of DMA read transactions (not PRD).")
- ;
-
- dmaWriteFullPages
- .name(name() + ".dma_write_full_pages")
- .desc("Number of full page size DMA writes.")
- ;
- dmaWriteBytes
- .name(name() + ".dma_write_bytes")
- .desc("Number of bytes transfered via DMA writes.")
- ;
- dmaWriteTxs
- .name(name() + ".dma_write_txs")
- .desc("Number of DMA write transactions.")
- ;
-}
-
-void
-IdeDisk::doDmaRead()
+IdeDisk::doDmaDataRead()
{
/** @todo we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
diskDelay, totalDiskDelay);
- if (dmaInterface) {
- if (dmaInterface->busy()) {
- // reschedule after waiting period
- dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
- return;
- }
- Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
+ dmaReadWaitEvent.schedule(curTick + totalDiskDelay);
+}
- uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
- (uint32_t)curPrd.getByteCount());
- dmaInterfaceBytes = bytesInPage;
+void
+IdeDisk::doDmaRead()
+{
- if (bytesInPage == TheISA::VMPageSize)
- dmaReadFullPages++;
- dmaReadBytes += bytesInPage;
- dmaReadTxs++;
- dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
- curTick + totalDiskDelay, &dmaReadEvent);
+ if (!dmaReadCG) {
+ // clear out the data buffer
+ memset(dataBuffer, 0, MAX_DMA_SIZE);
+ dmaReadCG = new ChunkGenerator(curPrd.getBaseAddr(),
+ curPrd.getByteCount(), TheISA::PageBytes);
+
+ }
+ if (ctrl->dmaPending()) {
+ panic("shouldn't be reentant??");
+ dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+ return;
+ } else if (!dmaReadCG->done()) {
+ assert(dmaReadCG->complete() < MAX_DMA_SIZE);
+ ctrl->dmaRead(pciToDma(dmaReadCG->addr()), dmaReadCG->size(),
+ &dmaReadWaitEvent, dataBuffer + dmaReadCG->complete());
+ dmaReadCG->next();
} else {
- // schedule dmaReadEvent with sectorDelay (dmaReadDone)
- dmaReadEvent.schedule(curTick + totalDiskDelay);
+ assert(dmaReadCG->done());
+ delete dmaReadCG;
+ dmaReadCG = NULL;
+ dmaReadDone();
}
}
@@ -446,68 +386,14 @@ void
IdeDisk::dmaReadDone()
{
- Addr curAddr = 0, dmaAddr = 0;
- uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0;
-
- // continue to use the DMA interface until all pages are read
- if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) {
- // see if the interface is busy
- if (dmaInterface->busy()) {
- // reschedule after waiting period
- dmaReadEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
- return;
- }
-
- uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes;
- curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes;
- dmaAddr = pciToDma(curAddr);
-
- bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
- dmaInterfaceBytes += bytesInPage;
-
- if (bytesInPage == TheISA::VMPageSize)
- dmaReadFullPages++;
- dmaReadBytes += bytesInPage;
- dmaReadTxs++;
-
- dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
- curTick, &dmaReadEvent);
-
- return;
- }
-
- // set initial address
- curAddr = curPrd.getBaseAddr();
-
- // clear out the data buffer
- memset(dataBuffer, 0, MAX_DMA_SIZE);
-
- // read the data from memory via DMA into a data buffer
- while (bytesWritten < curPrd.getByteCount()) {
- if (cmdBytesLeft <= 0)
- panic("DMA data is larger than # of sectors specified\n");
-
- dmaAddr = pciToDma(curAddr);
-
- // calculate how many bytes are in the current page
- bytesLeft = curPrd.getByteCount() - bytesWritten;
- bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
+ uint32_t bytesWritten = 0;
- // copy the data from memory into the data buffer
- memcpy((void *)(dataBuffer + bytesWritten),
- physmem->dma_addr(dmaAddr, bytesInPage),
- bytesInPage);
-
- curAddr += bytesInPage;
- bytesWritten += bytesInPage;
- cmdBytesLeft -= bytesInPage;
- }
// write the data to the disk image
- for (bytesWritten = 0;
- bytesWritten < curPrd.getByteCount();
+ for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
bytesWritten += SectorSize) {
+ cmdBytesLeft -= SectorSize;
writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
}
@@ -522,117 +408,55 @@ IdeDisk::dmaReadDone()
}
void
-IdeDisk::doDmaWrite()
+IdeDisk::doDmaDataWrite()
{
/** @todo we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
+ uint32_t bytesRead = 0;
DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
diskDelay, totalDiskDelay);
- if (dmaInterface) {
- if (dmaInterface->busy()) {
- // reschedule after waiting period
- dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
- return;
- }
-
- Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
-
- uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
- (uint32_t)curPrd.getByteCount());
+ memset(dataBuffer, 0, MAX_DMA_SIZE);
+ assert(cmdBytesLeft <= MAX_DMA_SIZE);
+ while (bytesRead < curPrd.getByteCount()) {
+ readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
+ bytesRead += SectorSize;
+ cmdBytesLeft -= SectorSize;
+ }
- dmaInterfaceBytes = bytesInPage;
+ dmaWriteWaitEvent.schedule(curTick + totalDiskDelay);
+}
- if (bytesInPage == TheISA::VMPageSize)
- dmaWriteFullPages++;
- dmaWriteBytes += bytesInPage;
- dmaWriteTxs++;
+void
+IdeDisk::doDmaWrite()
+{
- dmaInterface->doDMA(WriteInvalidate, dmaAddr,
- bytesInPage, curTick + totalDiskDelay,
- &dmaWriteEvent);
+ if (!dmaWriteCG) {
+ // clear out the data buffer
+ dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
+ curPrd.getByteCount(), TheISA::PageBytes);
+ }
+ if (ctrl->dmaPending()) {
+ panic("shouldn't be reentant??");
+ dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+ return;
+ } else if (!dmaWriteCG->done()) {
+ assert(dmaWriteCG->complete() < MAX_DMA_SIZE);
+ ctrl->dmaWrite(pciToDma(dmaWriteCG->addr()), dmaWriteCG->size(),
+ &dmaWriteWaitEvent, dataBuffer + dmaWriteCG->complete());
+ dmaWriteCG->next();
} else {
- // schedule event with disk delay (dmaWriteDone)
- dmaWriteEvent.schedule(curTick + totalDiskDelay);
+ assert(dmaWriteCG->done());
+ delete dmaWriteCG;
+ dmaWriteCG = NULL;
+ dmaWriteDone();
}
}
void
IdeDisk::dmaWriteDone()
{
- Addr curAddr = 0, pageAddr = 0, dmaAddr = 0;
- uint32_t bytesRead = 0, bytesInPage = 0;
-
- // continue to use the DMA interface until all pages are read
- if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) {
- // see if the interface is busy
- if (dmaInterface->busy()) {
- // reschedule after waiting period
- dmaWriteEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
- return;
- }
-
- uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes;
- curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes;
- dmaAddr = pciToDma(curAddr);
-
- bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
- dmaInterfaceBytes += bytesInPage;
-
- if (bytesInPage == TheISA::VMPageSize)
- dmaWriteFullPages++;
- dmaWriteBytes += bytesInPage;
- dmaWriteTxs++;
-
- dmaInterface->doDMA(WriteInvalidate, dmaAddr,
- bytesInPage, curTick,
- &dmaWriteEvent);
-
- return;
- }
-
- // setup the initial page and DMA address
- curAddr = curPrd.getBaseAddr();
- pageAddr = TheISA::TruncPage(curAddr);
- dmaAddr = pciToDma(curAddr);
-
- // clear out the data buffer
- memset(dataBuffer, 0, MAX_DMA_SIZE);
-
- while (bytesRead < curPrd.getByteCount()) {
- // see if we have crossed into a new page
- if (pageAddr != TheISA::TruncPage(curAddr)) {
- // write the data to memory
- memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
- (void *)(dataBuffer + (bytesRead - bytesInPage)),
- bytesInPage);
-
- // update the DMA address and page address
- pageAddr = TheISA::TruncPage(curAddr);
- dmaAddr = pciToDma(curAddr);
-
- bytesInPage = 0;
- }
-
- if (cmdBytesLeft <= 0)
- panic("DMA requested data is larger than # sectors specified\n");
-
- readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
-
- curAddr += SectorSize;
- bytesRead += SectorSize;
- bytesInPage += SectorSize;
- cmdBytesLeft -= SectorSize;
- }
-
- // write the last page worth read to memory
- if (bytesInPage != 0) {
- memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
- (void *)(dataBuffer + (bytesRead - bytesInPage)),
- bytesInPage);
- }
-
// check for the EOT
if (curPrd.getEOT()) {
assert(cmdBytesLeft == 0);
@@ -1188,13 +1012,13 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_SCALAR(curPrd.entry.endOfTable);
SERIALIZE_SCALAR(curPrdAddr);
+ /** @todo need to serialized chunk generator stuff!! */
// Serialize current transfer related information
SERIALIZE_SCALAR(cmdBytesLeft);
SERIALIZE_SCALAR(cmdBytes);
SERIALIZE_SCALAR(drqBytesLeft);
SERIALIZE_SCALAR(curSector);
SERIALIZE_SCALAR(dmaRead);
- SERIALIZE_SCALAR(dmaInterfaceBytes);
SERIALIZE_SCALAR(intrPending);
SERIALIZE_ENUM(devState);
SERIALIZE_ENUM(dmaState);
@@ -1240,13 +1064,13 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
UNSERIALIZE_SCALAR(curPrdAddr);
+ /** @todo need to serialized chunk generator stuff!! */
// Unserialize current transfer related information
UNSERIALIZE_SCALAR(cmdBytes);
UNSERIALIZE_SCALAR(cmdBytesLeft);
UNSERIALIZE_SCALAR(drqBytesLeft);
UNSERIALIZE_SCALAR(curSector);
UNSERIALIZE_SCALAR(dmaRead);
- UNSERIALIZE_SCALAR(dmaInterfaceBytes);
UNSERIALIZE_SCALAR(intrPending);
UNSERIALIZE_ENUM(devState);
UNSERIALIZE_ENUM(dmaState);
@@ -1260,7 +1084,6 @@ static const char *DriveID_strings[] = { "master", "slave" };
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
SimObjectParam<DiskImage *> image;
- SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<DriveID> driveID;
Param<int> delay;
@@ -1269,7 +1092,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"),
- INIT_PARAM(physmem, "Physical memory"),
INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
@@ -1278,7 +1100,7 @@ END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
CREATE_SIM_OBJECT(IdeDisk)
{
- return new IdeDisk(getInstanceName(), image, physmem, driveID, delay);
+ return new IdeDisk(getInstanceName(), image, driveID, delay);
}
REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)
diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh
index 402ae44ee..891c462b5 100644
--- a/dev/ide_disk.hh
+++ b/dev/ide_disk.hh
@@ -191,12 +191,8 @@ class IdeDisk : public SimObject
protected:
/** The IDE controller for this disk. */
IdeController *ctrl;
- /** The DMA interface to use for transfers */
- DMAInterface<Bus> *dmaInterface;
/** The image that contains the data of this disk. */
DiskImage *image;
- /** Pointer to physical memory for DMA transfers */
- PhysicalMemory *physmem;
protected:
/** The disk delay in microseconds. */
@@ -231,8 +227,6 @@ class IdeDisk : public SimObject
uint32_t curPrdAddr;
/** PRD entry */
PrdTableEntry curPrd;
- /** Number of bytes transfered by DMA interface for current transfer */
- uint32_t dmaInterfaceBytes;
/** Device ID (master=0/slave=1) */
int devID;
/** Interrupt pending */
@@ -250,12 +244,10 @@ class IdeDisk : public SimObject
* Create and initialize this Disk.
* @param name The name of this disk.
* @param img The disk image of this disk.
- * @param phys Pointer to physical memory
* @param id The disk ID (master=0/slave=1)
* @param disk_delay The disk delay in milliseconds
*/
- IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys,
- int id, Tick disk_delay);
+ IdeDisk(const std::string &name, DiskImage *img, int id, Tick disk_delay);
/**
* Delete the data buffer.
@@ -277,10 +269,9 @@ class IdeDisk : public SimObject
* Set the controller for this device
* @param c The IDE controller
*/
- void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) {
+ void setController(IdeController *c) {
if (ctrl) panic("Cannot change the controller once set!\n");
ctrl = c;
- dmaInterface = dmaIntr;
}
// Device register read/write
@@ -303,11 +294,17 @@ class IdeDisk : public SimObject
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
+ void doDmaDataRead();
+
void doDmaRead();
+ ChunkGenerator *dmaReadCG;
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
+ void doDmaDataWrite();
+
void doDmaWrite();
+ ChunkGenerator *dmaWriteCG;
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
@@ -353,8 +350,6 @@ class IdeDisk : public SimObject
inline Addr pciToDma(Addr pciAddr);
- uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft);
-
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
diff --git a/dev/io_device.cc b/dev/io_device.cc
index 6ab876ab8..24f33d84d 100644
--- a/dev/io_device.cc
+++ b/dev/io_device.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-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
@@ -27,31 +27,213 @@
*/
#include "dev/io_device.hh"
-#include "mem/bus/base_interface.hh"
-#include "mem/bus/dma_interface.hh"
#include "sim/builder.hh"
-PioDevice::PioDevice(const std::string &name, Platform *p)
- : FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0)
-{}
+
+PioPort::PioPort(PioDevice *dev, Platform *p)
+ : device(dev), platform(p)
+{ }
+
+
+Tick
+PioPort::recvAtomic(Packet &pkt)
+{
+ return device->recvAtomic(pkt);
+}
+
+void
+PioPort::recvFunctional(Packet &pkt)
+{
+ device->recvAtomic(pkt);
+}
+
+void
+PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+{
+ snoop.clear();
+ device->addressRanges(resp);
+}
+
+
+Packet *
+PioPort::recvRetry()
+{
+ Packet* pkt = transmitList.front();
+ transmitList.pop_front();
+ return pkt;
+}
+
+
+void
+PioPort::SendEvent::process()
+{
+ if (port->Port::sendTiming(packet) == Success)
+ return;
+
+ port->transmitList.push_back(&packet);
+}
+
+
+bool
+PioPort::recvTiming(Packet &pkt)
+{
+ device->recvAtomic(pkt);
+ sendTiming(pkt, pkt.time-pkt.req->getTime());
+ return Success;
+}
PioDevice::~PioDevice()
{
- if (pioInterface)
- delete pioInterface;
+ if (pioPort)
+ delete pioPort;
}
-DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
+void
+PioDevice::init()
+{
+ if (!pioPort)
+ panic("Pio port not connected to anything!");
+ pioPort->sendStatusChange(Port::RangeChange);
+}
-DmaDevice::DmaDevice(const std::string &name, Platform *p)
- : PioDevice(name, p), dmaInterface(NULL)
-{}
+void
+BasicPioDevice::addressRanges(AddrRangeList &range_list)
+{
+ assert(pioSize != 0);
+ range_list.clear();
+ range_list.push_back(RangeSize(pioAddr, pioSize));
+}
+
+
+DmaPort::DmaPort(DmaDevice *dev, Platform *p)
+ : device(dev), platform(p), pendingCount(0)
+{ }
+
+bool
+DmaPort::recvTiming(Packet &pkt)
+{
+ if (pkt.senderState) {
+ DmaReqState *state;
+ state = (DmaReqState*)pkt.senderState;
+ state->completionEvent->schedule(pkt.time - pkt.req->getTime());
+ delete pkt.req;
+ delete &pkt;
+ } else {
+ delete pkt.req;
+ delete &pkt;
+ }
+
+ return Success;
+}
+
+DmaDevice::DmaDevice(Params *p)
+ : PioDevice(p), dmaPort(NULL)
+{ }
+
+void
+DmaPort::SendEvent::process()
+{
+ if (port->Port::sendTiming(packet) == Success)
+ return;
+
+ port->transmitList.push_back(&packet);
+}
+
+Packet *
+DmaPort::recvRetry()
+{
+ Packet* pkt = transmitList.front();
+ transmitList.pop_front();
+ return pkt;
+}
+void
+DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
+ uint8_t *data)
+{
+
+ assert(event);
+
+ int prevSize = 0;
+ Packet basePkt;
+ Request baseReq(false);
+
+ basePkt.flags = 0;
+ basePkt.coherence = NULL;
+ basePkt.senderState = NULL;
+ basePkt.src = 0;
+ basePkt.dest = 0;
+ basePkt.cmd = cmd;
+ basePkt.result = Unknown;
+ basePkt.req = NULL;
+// baseReq.nicReq = true;
+ baseReq.setTime(curTick);
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ Packet *pkt = new Packet(basePkt);
+ Request *req = new Request(baseReq);
+ pkt->addr = gen.addr();
+ pkt->size = gen.size();
+ pkt->req = req;
+ pkt->req->setPaddr(pkt->addr);
+ pkt->req->setSize(pkt->size);
+ // Increment the data pointer on a write
+ if (data)
+ pkt->dataStatic(data + prevSize) ;
+ prevSize += pkt->size;
+ // Set the last bit of the dma as the final packet for this dma
+ // and set it's completion event.
+ if (prevSize == size) {
+ DmaReqState *state = new DmaReqState(event, true);
+
+ pkt->senderState = (void*)state;
+ }
+ assert(pendingCount >= 0);
+ pendingCount++;
+ sendDma(pkt);
+ }
+ // since this isn't getting used and we want a check to make sure that all
+ // packets had data in them at some point.
+ basePkt.dataStatic((uint8_t*)NULL);
+}
+
+
+void
+DmaPort::sendDma(Packet *pkt)
+{
+ // some kind of selction between access methods
+ // more work is going to have to be done to make
+ // switching actually work
+ /* MemState state = device->platform->system->memState;
+
+ if (state == Timing) {
+ if (sendTiming(pkt) == Failure)
+ transmitList.push_back(&packet);
+ } else if (state == Atomic) {*/
+ sendAtomic(*pkt);
+ if (pkt->senderState) {
+ DmaReqState *state = (DmaReqState*)pkt->senderState;
+ state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
+ }
+ pendingCount--;
+ assert(pendingCount >= 0);
+ delete pkt->req;
+ delete pkt;
+
+/* } else if (state == Functional) {
+ sendFunctional(pkt);
+ // Is this correct???
+ completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime);
+ completionEvent == NULL;
+ } else
+ panic("Unknown memory command state.");
+ */
+}
DmaDevice::~DmaDevice()
{
- if (dmaInterface)
- delete dmaInterface;
+ if (dmaPort)
+ delete dmaPort;
}
-DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice)
diff --git a/dev/io_device.hh b/dev/io_device.hh
index bcfd062b9..e492ccf0b 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -29,34 +29,307 @@
#ifndef __DEV_IO_DEVICE_HH__
#define __DEV_IO_DEVICE_HH__
-#include "mem/functional/functional.hh"
+#include "base/chunk_generator.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet_impl.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_object.hh"
-class BaseInterface;
-class Bus;
-class HierParams;
class Platform;
-template <class BusType> class DMAInterface;
+class PioDevice;
+class DmaDevice;
+class System;
-class PioDevice : public FunctionalMemory
+/**
+ * The PioPort class is a programmed i/o port that all devices that are
+ * sensitive to an address range use. The port takes all the memory
+ * access types and roles them into one read() and write() call that the device
+ * must respond to. The device must also provide the addressRanges() function
+ * with which it returns the address ranges it is interested in. An extra
+ * sendTiming() function is implemented which takes an delay. In this way the
+ * device can immediatly call sendTiming(pkt, time) after processing a request
+ * and the request will be handled by the port even if the port bus the device
+ * connects to is blocked.
+ */
+class PioPort : public Port
+{
+ protected:
+ /** The device that this port serves. */
+ PioDevice *device;
+
+ /** The platform that device/port are in. This is used to select which mode
+ * we are currently operating in. */
+ Platform *platform;
+
+ /** A list of outgoing timing response packets that haven't been serviced
+ * yet. */
+ std::list<Packet*> transmitList;
+
+ /** The current status of the peer(bus) that we are connected to. */
+ Status peerStatus;
+
+ virtual bool recvTiming(Packet &pkt);
+
+ virtual Tick recvAtomic(Packet &pkt);
+
+ virtual void recvFunctional(Packet &pkt) ;
+
+ virtual void recvStatusChange(Status status)
+ { peerStatus = status; }
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+
+ /**
+ * This class is used to implemented sendTiming() with a delay. When a delay
+ * is requested a new event is created. When the event time expires it
+ * attempts to send the packet. If it cannot, the packet is pushed onto the
+ * transmit list to be sent when recvRetry() is called. */
+ class SendEvent : public Event
+ {
+ PioPort *port;
+ Packet packet;
+
+ SendEvent(PioPort *p, Packet &pkt, Tick t)
+ : Event(&mainEventQueue), packet(pkt)
+ { schedule(curTick + t); }
+
+ virtual void process();
+
+ virtual const char *description()
+ { return "Future scheduled sendTiming event"; }
+
+ friend class PioPort;
+ };
+
+ /** Schedule a sendTiming() event to be called in the future. */
+ void sendTiming(Packet &pkt, Tick time)
+ { new PioPort::SendEvent(this, pkt, time); }
+
+ /** This function pops the last element off the transmit list and sends it.*/
+ virtual Packet *recvRetry();
+
+ public:
+ PioPort(PioDevice *dev, Platform *p);
+
+ friend class PioPort::SendEvent;
+};
+
+
+struct DmaReqState
+{
+ Event *completionEvent;
+ bool final;
+ DmaReqState(Event *ce, bool f)
+ : completionEvent(ce), final(f)
+ {}
+};
+
+class DmaPort : public Port
{
protected:
+ DmaDevice *device;
+ std::list<Packet*> transmitList;
+
+ /** The platform that device/port are in. This is used to select which mode
+ * we are currently operating in. */
Platform *platform;
- BaseInterface *pioInterface;
- Tick pioLatency;
+
+ /** Number of outstanding packets the dma port has. */
+ int pendingCount;
+
+ virtual bool recvTiming(Packet &pkt);
+ virtual Tick recvAtomic(Packet &pkt)
+ { panic("dma port shouldn't be used for pio access."); }
+ virtual void recvFunctional(Packet &pkt)
+ { panic("dma port shouldn't be used for pio access."); }
+
+ virtual void recvStatusChange(Status status)
+ { ; }
+
+ virtual Packet *recvRetry() ;
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+ { resp.clear(); snoop.clear(); }
+
+ class SendEvent : public Event
+ {
+ DmaPort *port;
+ Packet packet;
+
+ SendEvent(PioPort *p, Packet &pkt, Tick t)
+ : Event(&mainEventQueue), packet(pkt)
+ { schedule(curTick + t); }
+
+ virtual void process();
+
+ virtual const char *description()
+ { return "Future scheduled sendTiming event"; }
+
+ friend class DmaPort;
+ };
+
+ void sendDma(Packet *pkt);
public:
- PioDevice(const std::string &name, Platform *p);
+ DmaPort(DmaDevice *dev, Platform *p);
+
+ void dmaAction(Command cmd, Addr addr, int size, Event *event,
+ uint8_t *data = NULL);
+
+ bool dmaPending() { return pendingCount > 0; }
+
+ friend class DmaPort::SendEvent;
+
+};
+
+/**
+ * This device is the base class which all devices senstive to an address range
+ * inherit from. There are three pure virtual functions which all devices must
+ * implement addressRanges(), read(), and write(). The magic do choose which
+ * mode we are in, etc is handled by the PioPort so the device doesn't have to
+ * bother.
+ */
+
+class PioDevice : public MemObject
+{
+ protected:
+
+ /** The platform we are in. This is used to decide what type of memory
+ * transaction we should perform. */
+ Platform *platform;
+
+ /** The pioPort that handles the requests for us and provides us requests
+ * that it sees. */
+ PioPort *pioPort;
+
+ virtual void addressRanges(AddrRangeList &range_list) = 0;
+
+ /** As far as the devices are concerned they only accept atomic transactions
+ * which are converted to either a write or a read. */
+ Tick recvAtomic(Packet &pkt)
+ { return pkt.cmd == Read ? this->read(pkt) : this->write(pkt); }
+
+ /** Pure virtual function that the device must implement. Called when a read
+ * command is recieved by the port.
+ * @param pkt Packet describing this request
+ * @return number of ticks it took to complete
+ */
+ virtual Tick read(Packet &pkt) = 0;
+
+ /** Pure virtual function that the device must implement. Called when a
+ * write command is recieved by the port.
+ * @param pkt Packet describing this request
+ * @return number of ticks it took to complete
+ */
+ virtual Tick write(Packet &pkt) = 0;
+
+ public:
+ /** Params struct which is extended through each device based on the
+ * parameters it needs. Since we are re-writing everything, we might as well
+ * start from the bottom this time. */
+
+ struct Params
+ {
+ std::string name;
+ Platform *platform;
+ System *system;
+ };
+
+ protected:
+ Params *_params;
+
+ public:
+ const Params *params() const { return _params; }
+
+ PioDevice(Params *p)
+ : MemObject(p->name), platform(p->platform), pioPort(NULL),
+ _params(p)
+ {}
+
virtual ~PioDevice();
+
+ virtual void init();
+
+ virtual Port *getPort(const std::string &if_name)
+ {
+ if (if_name == "pio") {
+ if (pioPort != NULL)
+ panic("pio port already connected to.");
+ pioPort = new PioPort(this, params()->platform);
+ return pioPort;
+ } else
+ return NULL;
+ }
+ friend class PioPort;
+
+};
+
+class BasicPioDevice : public PioDevice
+{
+ public:
+ struct Params : public PioDevice::Params
+ {
+ Addr pio_addr;
+ Tick pio_delay;
+ };
+
+ protected:
+ /** Address that the device listens to. */
+ Addr pioAddr;
+
+ /** Size that the device's address range. */
+ Addr pioSize;
+
+ /** Delay that the device experinces on an access. */
+ Tick pioDelay;
+
+ public:
+ BasicPioDevice(Params *p)
+ : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), pioDelay(p->pio_delay)
+ {}
+
+ /** return the address ranges that this device responds to.
+ * @params range_list range list to populate with ranges
+ */
+ void addressRanges(AddrRangeList &range_list);
+
};
class DmaDevice : public PioDevice
{
protected:
- DMAInterface<Bus> *dmaInterface;
+ DmaPort *dmaPort;
public:
- DmaDevice(const std::string &name, Platform *p);
+ DmaDevice(Params *p);
virtual ~DmaDevice();
+
+ void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
+ { dmaPort->dmaAction(Write, addr, size, event, data) ; }
+
+ void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL)
+ { dmaPort->dmaAction(Read, addr, size, event, data); }
+
+ bool dmaPending() { return dmaPort->dmaPending(); }
+
+ virtual Port *getPort(const std::string &if_name)
+ {
+ if (if_name == "pio") {
+ if (pioPort != NULL)
+ panic("pio port already connected to.");
+ pioPort = new PioPort(this, params()->platform);
+ return pioPort;
+ } else if (if_name == "dma") {
+ if (dmaPort != NULL)
+ panic("dma port already connected to.");
+ dmaPort = new DmaPort(this, params()->platform);
+ return dmaPort;
+ } else
+ return NULL;
+ }
+
+ friend class DmaPort;
};
+
#endif // __DEV_IO_DEVICE_HH__
diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc
index 2afebbded..2f392a41a 100644
--- a/dev/isa_fake.cc
+++ b/dev/isa_fake.cc
@@ -35,106 +35,87 @@
#include <vector>
#include "base/trace.hh"
-#include "cpu/exec_context.hh"
#include "dev/isa_fake.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
+#include "mem/packet.hh"
#include "sim/builder.hh"
#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)
- : PioDevice(name, NULL), addr(a)
+IsaFake::IsaFake(Params *p)
+ : BasicPioDevice(p)
{
- mmu->add_child(this, RangeSize(addr, size));
-
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &IsaFake::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- }
+ pioSize = p->pio_size;
}
-Fault
-IsaFake::read(MemReqPtr &req, uint8_t *data)
+Tick
+IsaFake::read(Packet &pkt)
{
- DPRINTF(Tsunami, "read va=%#x size=%d\n",
- req->vaddr, req->size);
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
-#if TRACING_ON
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
-#endif
+ pkt.time += pioDelay;
- switch (req->size) {
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size);
- case sizeof(uint64_t):
- *(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL;
- return NoFault;
+ switch (pkt.size) {
+ pkt.set(0xFFFFFFFFFFFFFFFFULL);
+ break;
case sizeof(uint32_t):
- *(uint32_t*)data = 0xFFFFFFFF;
- return NoFault;
+ pkt.set((uint32_t)0xFFFFFFFF);
+ break;
case sizeof(uint16_t):
- *(uint16_t*)data = 0xFFFF;
- return NoFault;
+ pkt.set((uint16_t)0xFFFF);
+ break;
case sizeof(uint8_t):
- *(uint8_t*)data = 0xFF;
- return NoFault;
-
+ pkt.set((uint8_t)0xFF);
+ break;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
- DPRINTFN("Isa FakeSMC ERROR: read daddr=%#x size=%d\n", daddr, req->size);
-
- return NoFault;
-}
-
-Fault
-IsaFake::write(MemReqPtr &req, const uint8_t *data)
-{
- DPRINTF(Tsunami, "write - va=%#x size=%d \n",
- req->vaddr, req->size);
-
- //:Addr daddr = (req->paddr & addr_mask) >> 6;
-
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
Tick
-IsaFake::cacheAccess(MemReqPtr &req)
+IsaFake::write(Packet &pkt)
{
- return curTick;
+ pkt.time += pioDelay;
+ DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size);
+ pkt.result = Success;
+ return pioDelay;
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> pio_bus;
+ Param<Addr> pio_addr;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
- Param<Addr> size;
+ Param<Addr> pio_size;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
END_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
BEGIN_INIT_SIM_OBJECT_PARAMS(IsaFake)
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
- INIT_PARAM_DFLT(size, "Size of address range", 0x8)
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(pio_size, "Size of address range"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(system, "system object")
END_INIT_SIM_OBJECT_PARAMS(IsaFake)
CREATE_SIM_OBJECT(IsaFake)
{
- return new IsaFake(getInstanceName(), addr, mmu, hier, pio_bus, size);
+ IsaFake::Params *p = new IsaFake::Params;
+ p->name = getInstanceName();
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->pio_size = pio_size;
+ p->platform = platform;
+ p->system = system;
+ return new IsaFake(p);
}
REGISTER_SIM_OBJECT("IsaFake", IsaFake)
diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh
index 73e40c681..29050833d 100644
--- a/dev/isa_fake.hh
+++ b/dev/isa_fake.hh
@@ -37,51 +37,42 @@
#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
* so that an mcheck doesn't occur when an os probes a piece of hw
* that doesn't exist (e.g. UARTs1-3).
*/
-class IsaFake : public PioDevice
+class IsaFake : public BasicPioDevice
{
- private:
- /** The address in memory that we respond to */
- Addr addr;
+ public:
+ struct Params : public BasicPioDevice::Params
+ {
+ Addr pio_size;
+ };
+ protected:
+ const Params *params() const { return (const Params*)_params; }
public:
/**
* The constructor for Tsunmami Fake just registers itself with the MMU.
- * @param name name of this device.
- * @param a address to respond to.
- * @param mmu the mmu we register with.
- * @param size number of addresses to respond to
+ * @param p params structure
*/
- IsaFake(const std::string &name, Addr a, MemoryController *mmu,
- HierParams *hier, Bus *pio_bus, Addr size = 0x8);
+ IsaFake(Params *p);
/**
* This read always returns -1.
* @param req The memory request.
* @param data Where to put the data.
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Tick read(Packet &pkt);
/**
* All writes are simply ignored.
* @param req The memory request.
* @param data the data to not write.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
-
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
+ virtual Tick write(Packet &pkt);
};
-#endif // __ISA_FAKE_HH__
+#endif // __TSUNAMI_FAKE_HH__
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index ed8c794f9..a2e224ed0 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -34,22 +34,18 @@
#include <deque>
#include <string>
+#include "arch/alpha/ev5.hh"
#include "base/inet.hh"
#include "cpu/exec_context.hh"
#include "dev/etherlink.hh"
#include "dev/ns_gige.hh"
#include "dev/pciconfigall.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/dma_interface.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
#include "sim/stats.hh"
-#include "arch/vtophys.hh"
+#include "sim/system.hh"
const char *NsRxStateStrings[] =
{
@@ -107,29 +103,9 @@ NSGigE::NSGigE(Params *p)
txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
acceptMulticast(false), acceptUnicast(false),
acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
- physmem(p->pmem), intrTick(0), cpuPendingIntr(false),
+ intrTick(0), cpuPendingIntr(false),
intrEvent(0), interface(0)
{
- if (p->pio_bus) {
- pioInterface = newPioInterface(name() + ".pio", p->hier,
- p->pio_bus, this,
- &NSGigE::cacheAccess);
- pioLatency = p->pio_latency * p->pio_bus->clockRate;
- }
-
- if (p->header_bus) {
- if (p->payload_bus)
- dmaInterface = new DMAInterface<Bus>(name() + ".dma",
- p->header_bus,
- p->payload_bus, 1,
- p->dma_no_allocate);
- else
- dmaInterface = new DMAInterface<Bus>(name() + ".dma",
- p->header_bus,
- p->header_bus, 1,
- p->dma_no_allocate);
- } else if (p->payload_bus)
- panic("Must define a header bus if defining a payload bus");
intrDelay = p->intr_delay;
dmaReadDelay = p->dma_read_delay;
@@ -483,30 +459,18 @@ NSGigE::regStats()
rxPacketRate = rxPackets / simSeconds;
}
-/**
- * This is to read the PCI general configuration registers
- */
-void
-NSGigE::readConfig(int offset, int size, uint8_t *data)
-{
- if (offset < PCI_DEVICE_SPECIFIC)
- PciDev::readConfig(offset, size, data);
- else
- panic("Device specific PCI config space not implemented!\n");
-}
/**
* This is to write to the PCI general configuration registers
*/
void
-NSGigE::writeConfig(int offset, int size, const uint8_t* data)
+NSGigE::writeConfig(int offset, const uint16_t data)
{
if (offset < PCI_DEVICE_SPECIFIC)
- PciDev::writeConfig(offset, size, data);
+ PciDev::writeConfig(offset, data);
else
panic("Device specific PCI config space not implemented!\n");
- // Need to catch writes to BARs to update the PIO interface
switch (offset) {
// seems to work fine without all these PCI settings, but i
// put in the IO to double check, an assertion will fail if we
@@ -516,39 +480,6 @@ NSGigE::writeConfig(int offset, int size, const uint8_t* data)
ioEnable = true;
else
ioEnable = false;
-
-#if 0
- if (config.data[offset] & PCI_CMD_BME) {
- bmEnabled = true;
- }
- else {
- bmEnabled = false;
- }
-
- if (config.data[offset] & PCI_CMD_MSE) {
- memEnable = true;
- }
- else {
- memEnable = false;
- }
-#endif
- break;
-
- case PCI0_BASE_ADDR0:
- if (BARAddrs[0] != 0) {
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
-
- BARAddrs[0] &= EV5::PAddrUncachedMask;
- }
- break;
- case PCI0_BASE_ADDR1:
- if (BARAddrs[1] != 0) {
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
-
- BARAddrs[1] &= EV5::PAddrUncachedMask;
- }
break;
}
}
@@ -557,15 +488,18 @@ NSGigE::writeConfig(int offset, int size, const uint8_t* data)
* This reads the device registers, which are detailed in the NS83820
* spec sheet
*/
-Fault
-NSGigE::read(MemReqPtr &req, uint8_t *data)
+Tick
+NSGigE::read(Packet &pkt)
{
assert(ioEnable);
+ pkt.time += pioDelay;
+ pkt.allocate();
+
//The mask is to give you only the offset into the device register file
- Addr daddr = req->paddr & 0xfff;
- DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n",
- daddr, req->paddr, req->vaddr, req->size);
+ Addr daddr = pkt.addr & 0xfff;
+ DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
+ daddr, pkt.addr, pkt.size);
// there are some reserved registers, you can see ns_gige_reg.h and
@@ -573,240 +507,246 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
- readConfig(daddr & 0xff, req->size, data);
- return NoFault;
+ if (pkt.size == sizeof(uint8_t))
+ readConfig(daddr & 0xff, pkt.getPtr<uint8_t>());
+ if (pkt.size == sizeof(uint16_t))
+ readConfig(daddr & 0xff, pkt.getPtr<uint16_t>());
+ if (pkt.size == sizeof(uint32_t))
+ readConfig(daddr & 0xff, pkt.getPtr<uint32_t>());
+ pkt.result = Success;
+ return pioDelay;
} 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 NoFault;
+ pkt.set<uint32_t>(0);
+ pkt.result = Success;
+ return pioDelay;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
- switch (req->size) {
- case sizeof(uint32_t):
- {
- uint32_t &reg = *(uint32_t *)data;
- uint16_t rfaddr;
-
- switch (daddr) {
- case CR:
- reg = regs.command;
- //these are supposed to be cleared on a read
- reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
- break;
+ assert(pkt.size == sizeof(uint32_t));
+ uint32_t &reg = *pkt.getPtr<uint32_t>();
+ uint16_t rfaddr;
- case CFGR:
- reg = regs.config;
- break;
+ switch (daddr) {
+ case CR:
+ reg = regs.command;
+ //these are supposed to be cleared on a read
+ reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
+ break;
- case MEAR:
- reg = regs.mear;
- break;
+ case CFGR:
+ reg = regs.config;
+ break;
- case PTSCR:
- reg = regs.ptscr;
- break;
+ case MEAR:
+ reg = regs.mear;
+ break;
- case ISR:
- reg = regs.isr;
- devIntrClear(ISR_ALL);
- break;
+ case PTSCR:
+ reg = regs.ptscr;
+ break;
- case IMR:
- reg = regs.imr;
- break;
+ case ISR:
+ reg = regs.isr;
+ devIntrClear(ISR_ALL);
+ break;
- case IER:
- reg = regs.ier;
- break;
+ case IMR:
+ reg = regs.imr;
+ break;
- case IHR:
- reg = regs.ihr;
- break;
+ case IER:
+ reg = regs.ier;
+ break;
- case TXDP:
- reg = regs.txdp;
- break;
+ case IHR:
+ reg = regs.ihr;
+ break;
- case TXDP_HI:
- reg = regs.txdp_hi;
- break;
+ case TXDP:
+ reg = regs.txdp;
+ break;
- case TX_CFG:
- reg = regs.txcfg;
- break;
+ case TXDP_HI:
+ reg = regs.txdp_hi;
+ break;
- case GPIOR:
- reg = regs.gpior;
- break;
+ case TX_CFG:
+ reg = regs.txcfg;
+ break;
- case RXDP:
- reg = regs.rxdp;
- break;
+ case GPIOR:
+ reg = regs.gpior;
+ break;
- case RXDP_HI:
- reg = regs.rxdp_hi;
- break;
+ case RXDP:
+ reg = regs.rxdp;
+ break;
- case RX_CFG:
- reg = regs.rxcfg;
- break;
+ case RXDP_HI:
+ reg = regs.rxdp_hi;
+ break;
- case PQCR:
- reg = regs.pqcr;
- break;
+ case RX_CFG:
+ reg = regs.rxcfg;
+ break;
- case WCSR:
- reg = regs.wcsr;
- break;
+ case PQCR:
+ reg = regs.pqcr;
+ break;
- case PCR:
- reg = regs.pcr;
- break;
+ case WCSR:
+ reg = regs.wcsr;
+ break;
+
+ case PCR:
+ reg = regs.pcr;
+ break;
+
+ // see the spec sheet for how RFCR and RFDR work
+ // basically, you write to RFCR to tell the machine
+ // what you want to do next, then you act upon RFDR,
+ // and the device will be prepared b/c of what you
+ // wrote to RFCR
+ case RFCR:
+ reg = regs.rfcr;
+ break;
- // see the spec sheet for how RFCR and RFDR work
- // basically, you write to RFCR to tell the machine
- // what you want to do next, then you act upon RFDR,
- // and the device will be prepared b/c of what you
- // wrote to RFCR
- case RFCR:
- reg = regs.rfcr;
+ case RFDR:
+ rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
+ switch (rfaddr) {
+ // Read from perfect match ROM octets
+ case 0x000:
+ reg = rom.perfectMatch[1];
+ reg = reg << 8;
+ reg += rom.perfectMatch[0];
+ break;
+ case 0x002:
+ reg = rom.perfectMatch[3] << 8;
+ reg += rom.perfectMatch[2];
break;
+ case 0x004:
+ reg = rom.perfectMatch[5] << 8;
+ reg += rom.perfectMatch[4];
+ break;
+ default:
+ // Read filter hash table
+ if (rfaddr >= FHASH_ADDR &&
+ rfaddr < FHASH_ADDR + FHASH_SIZE) {
- case RFDR:
- rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
- switch (rfaddr) {
- // Read from perfect match ROM octets
- case 0x000:
- reg = rom.perfectMatch[1];
- reg = reg << 8;
- reg += rom.perfectMatch[0];
- break;
- case 0x002:
- reg = rom.perfectMatch[3] << 8;
- reg += rom.perfectMatch[2];
- break;
- case 0x004:
- reg = rom.perfectMatch[5] << 8;
- reg += rom.perfectMatch[4];
- break;
- default:
- // Read filter hash table
- if (rfaddr >= FHASH_ADDR &&
- rfaddr < FHASH_ADDR + FHASH_SIZE) {
-
- // Only word-aligned reads supported
- if (rfaddr % 2)
- panic("unaligned read from filter hash table!");
-
- reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
- reg += rom.filterHash[rfaddr - FHASH_ADDR];
- break;
- }
+ // Only word-aligned reads supported
+ if (rfaddr % 2)
+ panic("unaligned read from filter hash table!");
- panic("reading RFDR for something other than pattern"
- " matching or hashing! %#x\n", rfaddr);
+ reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
+ reg += rom.filterHash[rfaddr - FHASH_ADDR];
+ break;
}
- break;
- case SRR:
- reg = regs.srr;
- break;
+ panic("reading RFDR for something other than pattern"
+ " matching or hashing! %#x\n", rfaddr);
+ }
+ break;
- case MIBC:
- reg = regs.mibc;
- reg &= ~(MIBC_MIBS | MIBC_ACLR);
- break;
+ case SRR:
+ reg = regs.srr;
+ break;
- case VRCR:
- reg = regs.vrcr;
- break;
+ case MIBC:
+ reg = regs.mibc;
+ reg &= ~(MIBC_MIBS | MIBC_ACLR);
+ break;
- case VTCR:
- reg = regs.vtcr;
- break;
+ case VRCR:
+ reg = regs.vrcr;
+ break;
- case VDR:
- reg = regs.vdr;
- break;
+ case VTCR:
+ reg = regs.vtcr;
+ break;
- case CCSR:
- reg = regs.ccsr;
- break;
+ case VDR:
+ reg = regs.vdr;
+ break;
- case TBICR:
- reg = regs.tbicr;
- break;
+ case CCSR:
+ reg = regs.ccsr;
+ break;
- case TBISR:
- reg = regs.tbisr;
- break;
+ case TBICR:
+ reg = regs.tbicr;
+ break;
- case TANAR:
- reg = regs.tanar;
- break;
+ case TBISR:
+ reg = regs.tbisr;
+ break;
- case TANLPAR:
- reg = regs.tanlpar;
- break;
+ case TANAR:
+ reg = regs.tanar;
+ break;
- case TANER:
- reg = regs.taner;
- break;
+ case TANLPAR:
+ reg = regs.tanlpar;
+ break;
- case TESR:
- reg = regs.tesr;
- break;
+ case TANER:
+ reg = regs.taner;
+ break;
- case M5REG:
- reg = 0;
- if (params()->rx_thread)
- reg |= M5REG_RX_THREAD;
- if (params()->tx_thread)
- reg |= M5REG_TX_THREAD;
- if (params()->rss)
- reg |= M5REG_RSS;
- break;
+ case TESR:
+ reg = regs.tesr;
+ break;
- default:
- panic("reading unimplemented register: addr=%#x", daddr);
- }
+ case M5REG:
+ reg = 0;
+ if (params()->rx_thread)
+ reg |= M5REG_RX_THREAD;
+ if (params()->tx_thread)
+ reg |= M5REG_TX_THREAD;
+ if (params()->rss)
+ reg |= M5REG_RSS;
+ break;
- DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
- daddr, reg, reg);
+ default:
+ panic("reading unimplemented register: addr=%#x", daddr);
}
- break;
- default:
- panic("accessing register with invalid size: addr=%#x, size=%d",
- daddr, req->size);
- }
+ DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
+ daddr, reg, reg);
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
-Fault
-NSGigE::write(MemReqPtr &req, const uint8_t *data)
+Tick
+NSGigE::write(Packet &pkt)
{
assert(ioEnable);
- Addr daddr = req->paddr & 0xfff;
- DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n",
- daddr, req->paddr, req->vaddr, req->size);
+ Addr daddr = pkt.addr & 0xfff;
+ DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
+ daddr, pkt.addr, pkt.size);
+
+ pkt.time += pioDelay;
if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
- writeConfig(daddr & 0xff, req->size, data);
- return NoFault;
+ if (pkt.size == sizeof(uint8_t))
+ writeConfig(daddr & 0xff, pkt.get<uint8_t>());
+ if (pkt.size == sizeof(uint16_t))
+ writeConfig(daddr & 0xff, pkt.get<uint16_t>());
+ if (pkt.size == sizeof(uint32_t))
+ writeConfig(daddr & 0xff, pkt.get<uint32_t>());
+ pkt.result = Success;
+ return pioDelay;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
- if (req->size == sizeof(uint32_t)) {
- uint32_t reg = *(uint32_t *)data;
+ if (pkt.size == sizeof(uint32_t)) {
+ uint32_t reg = pkt.get<uint32_t>();
uint16_t rfaddr;
DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
@@ -1192,8 +1132,8 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
} else {
panic("Invalid Request Size");
}
-
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
void
@@ -1443,42 +1383,17 @@ NSGigE::regsReset()
acceptArp = false;
}
-void
-NSGigE::rxDmaReadCopy()
-{
- assert(rxDmaState == dmaReading);
-
- physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen);
- rxDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n",
- rxDmaAddr, rxDmaLen);
- DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
-}
-
bool
NSGigE::doRxDmaRead()
{
assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
rxDmaState = dmaReading;
- if (dmaInterface && !rxDmaFree) {
- if (dmaInterface->busy())
- rxDmaState = dmaReadWaiting;
- else
- dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick,
- &rxDmaReadEvent, true);
- return true;
- }
-
- if (dmaReadDelay == 0 && dmaReadFactor == 0) {
- rxDmaReadCopy();
- return false;
- }
+ if (dmaPending())
+ rxDmaState = dmaReadWaiting;
+ else
+ dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
- Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
- Tick start = curTick + dmaReadDelay + factor;
- rxDmaReadEvent.schedule(start);
return true;
}
@@ -1486,7 +1401,11 @@ void
NSGigE::rxDmaReadDone()
{
assert(rxDmaState == dmaReading);
- rxDmaReadCopy();
+ rxDmaState = dmaIdle;
+
+ DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n",
+ rxDmaAddr, rxDmaLen);
+ DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
// If the transmit state machine has a pending DMA, let it go first
if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
@@ -1495,42 +1414,16 @@ NSGigE::rxDmaReadDone()
rxKick();
}
-void
-NSGigE::rxDmaWriteCopy()
-{
- assert(rxDmaState == dmaWriting);
-
- physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
- rxDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
- rxDmaAddr, rxDmaLen);
- DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
-}
-
bool
NSGigE::doRxDmaWrite()
{
assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
rxDmaState = dmaWriting;
- if (dmaInterface && !rxDmaFree) {
- if (dmaInterface->busy())
- rxDmaState = dmaWriteWaiting;
- else
- dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick,
- &rxDmaWriteEvent, true);
- return true;
- }
-
- if (dmaWriteDelay == 0 && dmaWriteFactor == 0) {
- rxDmaWriteCopy();
- return false;
- }
-
- Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
- Tick start = curTick + dmaWriteDelay + factor;
- rxDmaWriteEvent.schedule(start);
+ if (dmaPending())
+ rxDmaState = dmaWriteWaiting;
+ else
+ dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
return true;
}
@@ -1538,7 +1431,11 @@ void
NSGigE::rxDmaWriteDone()
{
assert(rxDmaState == dmaWriting);
- rxDmaWriteCopy();
+ rxDmaState = dmaIdle;
+
+ DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
+ rxDmaAddr, rxDmaLen);
+ DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
// If the transmit state machine has a pending DMA, let it go first
if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
@@ -1935,42 +1832,17 @@ NSGigE::transmit()
}
}
-void
-NSGigE::txDmaReadCopy()
-{
- assert(txDmaState == dmaReading);
-
- physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
- txDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
- txDmaAddr, txDmaLen);
- DDUMP(EthernetDMA, txDmaData, txDmaLen);
-}
-
bool
NSGigE::doTxDmaRead()
{
assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
txDmaState = dmaReading;
- if (dmaInterface && !txDmaFree) {
- if (dmaInterface->busy())
- txDmaState = dmaReadWaiting;
- else
- dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick,
- &txDmaReadEvent, true);
- return true;
- }
-
- if (dmaReadDelay == 0 && dmaReadFactor == 0.0) {
- txDmaReadCopy();
- return false;
- }
+ if (dmaPending())
+ txDmaState = dmaReadWaiting;
+ else
+ dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
- Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
- Tick start = curTick + dmaReadDelay + factor;
- txDmaReadEvent.schedule(start);
return true;
}
@@ -1978,7 +1850,11 @@ void
NSGigE::txDmaReadDone()
{
assert(txDmaState == dmaReading);
- txDmaReadCopy();
+ txDmaState = dmaIdle;
+
+ DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
+ txDmaAddr, txDmaLen);
+ DDUMP(EthernetDMA, txDmaData, txDmaLen);
// If the receive state machine has a pending DMA, let it go first
if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
@@ -1987,42 +1863,16 @@ NSGigE::txDmaReadDone()
txKick();
}
-void
-NSGigE::txDmaWriteCopy()
-{
- assert(txDmaState == dmaWriting);
-
- physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen);
- txDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
- txDmaAddr, txDmaLen);
- DDUMP(EthernetDMA, txDmaData, txDmaLen);
-}
-
bool
NSGigE::doTxDmaWrite()
{
assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
txDmaState = dmaWriting;
- if (dmaInterface && !txDmaFree) {
- if (dmaInterface->busy())
- txDmaState = dmaWriteWaiting;
- else
- dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick,
- &txDmaWriteEvent, true);
- return true;
- }
-
- if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) {
- txDmaWriteCopy();
- return false;
- }
-
- Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
- Tick start = curTick + dmaWriteDelay + factor;
- txDmaWriteEvent.schedule(start);
+ if (dmaPending())
+ txDmaState = dmaWriteWaiting;
+ else
+ dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
return true;
}
@@ -2030,7 +1880,11 @@ void
NSGigE::txDmaWriteDone()
{
assert(txDmaState == dmaWriting);
- txDmaWriteCopy();
+ txDmaState = dmaIdle;
+
+ DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
+ txDmaAddr, txDmaLen);
+ DDUMP(EthernetDMA, txDmaData, txDmaLen);
// If the receive state machine has a pending DMA, let it go first
if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
@@ -2147,7 +2001,7 @@ NSGigE::txKick()
case txFifoBlock:
if (!txPacket) {
DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
- txPacket = new PacketData(16384);
+ txPacket = new EthPacketData(16384);
txPacketBufPtr = txPacket->data;
}
@@ -2473,7 +2327,7 @@ NSGigE::transferDone()
}
bool
-NSGigE::rxFilter(const PacketPtr &packet)
+NSGigE::rxFilter(const EthPacketPtr &packet)
{
EthPtr eth = packet;
bool drop = true;
@@ -2516,7 +2370,7 @@ NSGigE::rxFilter(const PacketPtr &packet)
}
bool
-NSGigE::recvPacket(PacketPtr packet)
+NSGigE::recvPacket(EthPacketPtr packet)
{
rxBytes += packet->length;
rxPackets++;
@@ -2576,14 +2430,7 @@ NSGigE::serialize(ostream &os)
/*
* Finalize any DMA events now.
*/
- if (rxDmaReadEvent.scheduled())
- rxDmaReadCopy();
- if (rxDmaWriteEvent.scheduled())
- rxDmaWriteCopy();
- if (txDmaReadEvent.scheduled())
- txDmaReadCopy();
- if (txDmaWriteEvent.scheduled())
- txDmaWriteCopy();
+ // @todo will mem system save pending dma?
/*
* Serialize the device registers
@@ -2804,7 +2651,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
bool txPacketExists;
UNSERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
- txPacket = new PacketData(16384);
+ txPacket = new EthPacketData(16384);
txPacket->unserialize("txPacket", cp, section);
uint32_t txPktBufPtr;
UNSERIALIZE_SCALAR(txPktBufPtr);
@@ -2816,7 +2663,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(rxPacketExists);
rxPacket = 0;
if (rxPacketExists) {
- rxPacket = new PacketData(16384);
+ rxPacket = new EthPacketData(16384);
rxPacket->unserialize("rxPacket", cp, section);
uint32_t rxPktBufPtr;
UNSERIALIZE_SCALAR(rxPktBufPtr);
@@ -2925,23 +2772,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
intrEvent = new IntrEvent(this, true);
intrEvent->schedule(intrEventTick);
}
-
- /*
- * re-add addrRanges to bus bridges
- */
- if (pioInterface) {
- pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
- pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
- }
-}
-
-Tick
-NSGigE::cacheAccess(MemReqPtr &req)
-{
- DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
- req->paddr, req->paddr & 0xfff);
-
- return curTick + pioLatency;
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
@@ -2976,22 +2806,16 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
- Param<Tick> clock;
-
- Param<Addr> addr;
- SimObjectParam<MemoryController *> mmu;
- SimObjectParam<PhysicalMemory *> physmem;
+ SimObjectParam<System *> system;
+ SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
+ Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
- SimObjectParam<Bus*> pio_bus;
- SimObjectParam<Bus*> dma_bus;
- SimObjectParam<Bus*> payload_bus;
+ Param<Tick> clock;
Param<bool> dma_desc_free;
Param<bool> dma_data_free;
Param<Tick> dma_read_delay;
@@ -2999,7 +2823,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> dma_read_factor;
Param<Tick> dma_write_factor;
Param<bool> dma_no_allocate;
- Param<Tick> pio_latency;
Param<Tick> intr_delay;
Param<Tick> rx_delay;
@@ -3017,22 +2840,16 @@ END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
- INIT_PARAM(clock, "State machine processor frequency"),
-
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(physmem, "Physical Memory"),
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(platform, "Platform"),
- INIT_PARAM(pci_bus, "PCI bus"),
+ INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(clock, "State machine cycle time"),
- INIT_PARAM(hier, "Hierarchy global variables"),
- INIT_PARAM(pio_bus, ""),
- INIT_PARAM(dma_bus, ""),
- INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"),
INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"),
INIT_PARAM(dma_data_free, "DMA of Data is free"),
INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
@@ -3040,7 +2857,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
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(intr_delay, "Interrupt Delay in microseconds"),
INIT_PARAM(rx_delay, "Receive Delay"),
@@ -3062,22 +2878,16 @@ CREATE_SIM_OBJECT(NSGigE)
NSGigE::Params *params = new NSGigE::Params;
params->name = getInstanceName();
-
- params->clock = clock;
-
- params->mmu = mmu;
- params->pmem = physmem;
+ params->platform = platform;
+ params->system = system;
params->configSpace = configspace;
params->configData = configdata;
- params->plat = platform;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
params->functionNum = pci_func;
+ params->pio_delay = pio_latency;
- params->hier = hier;
- params->pio_bus = pio_bus;
- params->header_bus = dma_bus;
- params->payload_bus = payload_bus;
+ params->clock = clock;
params->dma_desc_free = dma_desc_free;
params->dma_data_free = dma_data_free;
params->dma_read_delay = dma_read_delay;
@@ -3085,7 +2895,7 @@ CREATE_SIM_OBJECT(NSGigE)
params->dma_read_factor = dma_read_factor;
params->dma_write_factor = dma_write_factor;
params->dma_no_allocate = dma_no_allocate;
- params->pio_latency = pio_latency;
+ params->pio_delay = pio_latency;
params->intr_delay = intr_delay;
params->rx_delay = rx_delay;
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 59c55056e..7bb422287 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -42,7 +42,6 @@
#include "dev/ns_gige_reg.h"
#include "dev/pcidev.hh"
#include "dev/pktfifo.hh"
-#include "mem/bus/bus.hh"
#include "sim/eventq.hh"
// Hash filtering constants
@@ -111,10 +110,7 @@ struct dp_rom {
};
class NSGigEInt;
-class PhysicalMemory;
-class BaseInterface;
-class HierParams;
-class Bus;
+class Packet;
class PciConfigAll;
/**
@@ -165,10 +161,6 @@ class NSGigE : public PciDev
eepromRead
};
- private:
- Addr addr;
- static const Addr size = sizeof(dp_regs);
-
protected:
/** device register file */
dp_regs regs;
@@ -187,8 +179,8 @@ class NSGigE : public PciDev
PacketFifo rxFifo;
/** various helper vars */
- PacketPtr txPacket;
- PacketPtr rxPacket;
+ EthPacketPtr txPacket;
+ EthPacketPtr rxPacket;
uint8_t *txPacketBufPtr;
uint8_t *rxPacketBufPtr;
uint32_t txXferLen;
@@ -258,16 +250,12 @@ class NSGigE : public PciDev
int rxDmaLen;
bool doRxDmaRead();
bool doRxDmaWrite();
- void rxDmaReadCopy();
- void rxDmaWriteCopy();
void *txDmaData;
Addr txDmaAddr;
int txDmaLen;
bool doTxDmaRead();
bool doTxDmaWrite();
- void txDmaReadCopy();
- void txDmaWriteCopy();
void rxDmaReadDone();
friend class EventWrapper<NSGigE, &NSGigE::rxDmaReadDone>;
@@ -331,7 +319,7 @@ class NSGigE : public PciDev
* receive address filter
*/
bool rxFilterEnable;
- bool rxFilter(const PacketPtr &packet);
+ bool rxFilter(const EthPacketPtr &packet);
bool acceptBroadcast;
bool acceptMulticast;
bool acceptUnicast;
@@ -339,8 +327,6 @@ class NSGigE : public PciDev
bool acceptArp;
bool multicastHashEnable;
- PhysicalMemory *physmem;
-
/**
* Interrupt management
*/
@@ -363,16 +349,10 @@ class NSGigE : public PciDev
public:
struct Params : public PciDev::Params
{
- PhysicalMemory *pmem;
- HierParams *hier;
- Bus *pio_bus;
- Bus *header_bus;
- Bus *payload_bus;
Tick clock;
Tick intr_delay;
Tick tx_delay;
Tick rx_delay;
- Tick pio_latency;
bool dma_desc_free;
bool dma_data_free;
Tick dma_read_delay;
@@ -393,16 +373,15 @@ class NSGigE : public PciDev
~NSGigE();
const Params *params() const { return (const Params *)_params; }
- virtual void writeConfig(int offset, int size, const uint8_t *data);
- virtual void readConfig(int offset, int size, uint8_t *data);
+ virtual void writeConfig(int offset, const uint16_t data);
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
bool cpuIntrPending() const;
void cpuIntrAck() { cpuIntrClear(); }
- bool recvPacket(PacketPtr packet);
+ bool recvPacket(EthPacketPtr packet);
void transferDone();
void setInterface(NSGigEInt *i) { assert(!interface); interface = i; }
@@ -463,9 +442,6 @@ class NSGigE : public PciDev
Stats::Formula coalescedTotal;
Stats::Scalar<> postedInterrupts;
Stats::Scalar<> droppedPackets;
-
- public:
- Tick cacheAccess(MemReqPtr &req);
};
/*
@@ -480,7 +456,7 @@ class NSGigEInt : public EtherInt
NSGigEInt(const std::string &name, NSGigE *d)
: EtherInt(name), dev(d) { dev->setInterface(this); }
- virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
+ virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); }
};
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index d55084fa5..dfb1d48f6 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -39,29 +39,21 @@
#include "dev/pciconfigall.hh"
#include "dev/pcidev.hh"
#include "dev/pcireg.h"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
+#include "dev/platform.hh"
+#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
using namespace std;
-using namespace TheISA;
-PciConfigAll::PciConfigAll(const string &name,
- Addr a, MemoryController *mmu,
- HierParams *hier, Bus *pio_bus, Tick pio_latency)
- : PioDevice(name, NULL), addr(a)
+PciConfigAll::PciConfigAll(Params *p)
+ : BasicPioDevice(p)
{
- mmu->add_child(this, RangeSize(addr, size));
+ pioSize = 0xffffff;
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &PciConfigAll::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- pioLatency = pio_latency * pio_bus->clockRate;
- }
+ // Set backpointer for pci config. Really the config stuff should be able to
+ // automagically do this
+ p->platform->pciconfig = this;
// Make all the pointers to devices null
for(int x=0; x < MAX_PCI_DEV; x++)
@@ -96,58 +88,59 @@ PciConfigAll::startup()
}
-Fault
-PciConfigAll::read(MemReqPtr &req, uint8_t *data)
+Tick
+PciConfigAll::read(Packet &pkt)
{
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
-
- DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n",
- req->vaddr, daddr, req->size);
-
+ Addr daddr = pkt.addr - pioAddr;
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
int reg = daddr & 0xFF;
- if (devices[device][func] == NULL) {
- switch (req->size) {
- // case sizeof(uint64_t):
- // *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF;
- // return NoFault;
- case sizeof(uint32_t):
- *(uint32_t*)data = 0xFFFFFFFF;
- return NoFault;
- case sizeof(uint16_t):
- *(uint16_t*)data = 0xFFFF;
- return NoFault;
- case sizeof(uint8_t):
- *(uint8_t*)data = 0xFF;
- return NoFault;
- default:
- panic("invalid access size(?) for PCI configspace!\n");
- }
- } else {
- switch (req->size) {
- case sizeof(uint32_t):
- case sizeof(uint16_t):
- case sizeof(uint8_t):
- devices[device][func]->readConfig(reg, req->size, data);
- return NoFault;
- default:
- panic("invalid access size(?) for PCI configspace!\n");
- }
+ pkt.time += pioDelay;
+ pkt.allocate();
+
+ DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt.addr, daddr,
+ pkt.size);
+
+ switch (pkt.size) {
+ case sizeof(uint32_t):
+ if (devices[device][func] == NULL)
+ pkt.set<uint32_t>(0xFFFFFFFF);
+ else
+ devices[device][func]->readConfig(reg, pkt.getPtr<uint32_t>());
+ break;
+ case sizeof(uint16_t):
+ if (devices[device][func] == NULL)
+ pkt.set<uint16_t>(0xFFFF);
+ else
+ devices[device][func]->readConfig(reg, pkt.getPtr<uint16_t>());
+ break;
+ case sizeof(uint8_t):
+ if (devices[device][func] == NULL)
+ pkt.set<uint8_t>(0xFF);
+ else
+ devices[device][func]->readConfig(reg, pkt.getPtr<uint8_t>());
+ break;
+ default:
+ panic("invalid access size(?) for PCI configspace!\n");
}
-
- DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n",
- daddr, req->size);
-
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
-Fault
-PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
+Tick
+PciConfigAll::write(Packet &pkt)
{
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ pkt.time += pioDelay;
+
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ assert(pkt.size == sizeof(uint8_t) || pkt.size == sizeof(uint16_t) ||
+ pkt.size == sizeof(uint32_t));
+ Addr daddr = pkt.addr - pioAddr;
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
@@ -155,17 +148,24 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
if (devices[device][func] == NULL)
panic("Attempting to write to config space on non-existant device\n");
- else if (req->size != sizeof(uint8_t) &&
- req->size != sizeof(uint16_t) &&
- req->size != sizeof(uint32_t))
- panic("invalid access size(?) for PCI configspace!\n");
DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
- req->vaddr, req->size, *(uint32_t*)data);
-
- devices[device][func]->writeConfig(reg, req->size, data);
-
- return NoFault;
+ pkt.addr, pkt.size, pkt.get<uint32_t>());
+
+ switch (pkt.size) {
+ case sizeof(uint8_t):
+ devices[device][func]->writeConfig(reg, pkt.get<uint8_t>());
+ break;
+ case sizeof(uint16_t):
+ devices[device][func]->writeConfig(reg, pkt.get<uint16_t>());
+ break;
+ case sizeof(uint32_t):
+ devices[device][func]->writeConfig(reg, pkt.get<uint32_t>());
+ break;
+ default:
+ panic("invalid pci config write size\n");
+ }
+ return pioDelay;
}
void
@@ -188,40 +188,34 @@ PciConfigAll::unserialize(Checkpoint *cp, const std::string &section)
*/
}
-Tick
-PciConfigAll::cacheAccess(MemReqPtr &req)
-{
- return curTick + pioLatency;
-}
-
#ifndef DOXYGEN_SHOULD_SKIP_THIS
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- Param<Addr> mask;
- SimObjectParam<Bus*> pio_bus;
+ Param<Addr> pio_addr;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM(mask, "Address Mask"),
- INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(system, "system object")
END_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
CREATE_SIM_OBJECT(PciConfigAll)
{
- return new PciConfigAll(getInstanceName(), addr, mmu, hier, pio_bus,
- pio_latency);
+ BasicPioDevice::Params *p = new BasicPioDevice::Params;
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->platform = platform;
+ p->system = system;
+ return new PciConfigAll(p);
}
REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll)
diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh
index c6a0241d8..2393b445e 100644
--- a/dev/pciconfigall.hh
+++ b/dev/pciconfigall.hh
@@ -43,7 +43,6 @@ static const uint32_t MAX_PCI_DEV = 32;
static const uint32_t MAX_PCI_FUNC = 8;
class PciDev;
-class MemoryController;
/**
* PCI Config Space
@@ -52,12 +51,9 @@ class MemoryController;
* space and passes the requests on to TsunamiPCIDev devices as
* appropriate.
*/
-class PciConfigAll : public PioDevice
+class PciConfigAll : public BasicPioDevice
{
private:
- Addr addr;
- static const Addr size = 0xffffff;
-
/**
* Pointers to all the devices that are registered with this
* particular config space.
@@ -67,15 +63,9 @@ class PciConfigAll : public PioDevice
public:
/**
* Constructor for PCIConfigAll
- * @param name name of the object
- * @param a base address of the write
- * @param mmu the memory controller
- * @param hier object to store parameters universal the device hierarchy
- * @param bus The bus that this device is attached to
+ * @param p parameters structure
*/
- PciConfigAll(const std::string &name, Addr a, MemoryController *mmu,
- HierParams *hier, Bus *pio_bus, Tick pio_latency);
-
+ PciConfigAll(Params *p);
/**
* Check if a device exists.
@@ -99,11 +89,10 @@ class PciConfigAll : public PioDevice
* Read something in PCI config space. If the device does not exist
* -1 is returned, if the device does exist its PciDev::ReadConfig (or the
* virtual function that overrides) it is called.
- * @param req Contains the address of the field to read.
- * @param data Return the field read.
- * @return The fault condition of the access.
+ * @param pkt Contains the address of the field to read.
+ * @return Amount of time to do the read
*/
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Tick read(Packet &pkt);
/**
* Write to PCI config spcae. If the device does not exit the simulator
@@ -114,7 +103,7 @@ class PciConfigAll : public PioDevice
* @return The fault condition of the access.
*/
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick write(Packet &pkt);
/**
* Start up function to check if more than one person is using an interrupt line
@@ -134,14 +123,6 @@ class PciConfigAll : public PioDevice
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
-
};
#endif // __PCICONFIGALL_HH__
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index a05ee3803..c40ef62e4 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -39,20 +39,20 @@
#include "base/misc.hh"
#include "base/str.hh" // for to_number
#include "base/trace.hh"
-#include "dev/pcidev.hh"
#include "dev/pciconfigall.hh"
-#include "mem/bus/bus.hh"
-#include "mem/functional/memory_control.hh"
+#include "dev/pcidev.hh"
+#include "dev/tsunamireg.h"
+#include "mem/packet.hh"
#include "sim/builder.hh"
+#include "sim/byteswap.hh"
#include "sim/param.hh"
#include "sim/root.hh"
-#include "dev/tsunamireg.h"
using namespace std;
PciDev::PciDev(Params *p)
- : DmaDevice(p->name, p->plat), _params(p), plat(p->plat),
- configData(p->configData)
+ : DmaDevice(p), plat(p->platform), configData(p->configData),
+ pioDelay(p->pio_delay)
{
// copy the config data from the PciConfigData object
if (configData) {
@@ -70,214 +70,180 @@ PciDev::PciDev(Params *p)
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
}
-Fault
-PciDev::read(MemReqPtr &req, uint8_t *data)
-{ return NoFault; }
-
-Fault
-PciDev::write(MemReqPtr &req, const uint8_t *data)
-{ return NoFault; }
-
-Fault
-PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::readBar1(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
+void
+PciDev::readConfig(int offset, uint8_t *data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
-Fault
-PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
+ *data = config.data[offset];
-Fault
-PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, *data);
+}
-Fault
-PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
+void
+PciDev::addressRanges(AddrRangeList &range_list)
+{
+ int x = 0;
+ range_list.clear();
+ for (x = 0; x < 6; x++)
+ if (BARAddrs[x] != 0)
+ range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
+}
-Fault
-PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
+void
+PciDev::readConfig(int offset, uint16_t *data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
-Fault
-PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
+ *data = *(uint16_t*)&config.data[offset];
-Fault
-PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, *data);
+}
-Fault
-PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
+void
+PciDev::readConfig(int offset, uint32_t *data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
-Fault
-PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
+ *data = *(uint32_t*)&config.data[offset];
-Fault
-PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, *data);
+}
-Fault
-PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
void
-PciDev::readConfig(int offset, int size, uint8_t *data)
+PciDev::writeConfig(int offset, const uint8_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
- switch(size) {
- case sizeof(uint8_t):
- *data = config.data[offset];
- break;
- case sizeof(uint16_t):
- *(uint16_t*)data = *(uint16_t*)&config.data[offset];
+ DPRINTF(PCIDEV,
+ "write device: %#x function: %#x reg: %#x size: 1 data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, data);
+
+ switch (offset) {
+ case PCI0_INTERRUPT_LINE:
+ config.interruptLine = data;
+ case PCI_CACHE_LINE_SIZE:
+ config.cacheLineSize = data;
+ case PCI_LATENCY_TIMER:
+ config.latencyTimer = data;
break;
- case sizeof(uint32_t):
- *(uint32_t*)data = *(uint32_t*)&config.data[offset];
+ /* Do nothing for these read-only registers */
+ case PCI0_INTERRUPT_PIN:
+ case PCI0_MINIMUM_GRANT:
+ case PCI0_MAXIMUM_LATENCY:
+ case PCI_CLASS_CODE:
+ case PCI_REVISION_ID:
break;
default:
- panic("Invalid PCI configuration read size!\n");
+ panic("writing to a read only register");
}
-
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, size,
- *(uint32_t*)data);
}
void
-PciDev::writeConfig(int offset, int size, const uint8_t *data)
+PciDev::writeConfig(int offset, const uint16_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
- uint8_t &data8 = *(uint8_t*)data;
- uint16_t &data16 = *(uint16_t*)data;
- uint32_t &data32 = *(uint32_t*)data;
-
DPRINTF(PCIDEV,
- "write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, size, data32);
-
- switch (size) {
- case sizeof(uint8_t): // 1-byte access
- switch (offset) {
- case PCI0_INTERRUPT_LINE:
- config.interruptLine = data8;
- case PCI_CACHE_LINE_SIZE:
- config.cacheLineSize = data8;
- case PCI_LATENCY_TIMER:
- config.latencyTimer = data8;
- break;
- /* Do nothing for these read-only registers */
- case PCI0_INTERRUPT_PIN:
- case PCI0_MINIMUM_GRANT:
- case PCI0_MAXIMUM_LATENCY:
- case PCI_CLASS_CODE:
- case PCI_REVISION_ID:
- break;
- default:
- panic("writing to a read only register");
- }
+ "write device: %#x function: %#x reg: %#x size: 2 data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, data);
+
+ switch (offset) {
+ case PCI_COMMAND:
+ config.command = data;
+ case PCI_STATUS:
+ config.status = data;
+ case PCI_CACHE_LINE_SIZE:
+ config.cacheLineSize = data;
break;
+ default:
+ panic("writing to a read only register");
+ }
+}
- case sizeof(uint16_t): // 2-byte access
- switch (offset) {
- case PCI_COMMAND:
- config.command = data16;
- case PCI_STATUS:
- config.status = data16;
- case PCI_CACHE_LINE_SIZE:
- config.cacheLineSize = data16;
- break;
- default:
- panic("writing to a read only register");
- }
- break;
- case sizeof(uint32_t): // 4-byte access
- switch (offset) {
- case PCI0_BASE_ADDR0:
- case PCI0_BASE_ADDR1:
- case PCI0_BASE_ADDR2:
- case PCI0_BASE_ADDR3:
- case PCI0_BASE_ADDR4:
- case PCI0_BASE_ADDR5:
-
- uint32_t barnum, bar_mask;
- Addr base_addr, base_size, space_base;
-
- barnum = BAR_NUMBER(offset);
-
- if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
- bar_mask = BAR_IO_MASK;
- space_base = TSUNAMI_PCI0_IO;
- } else {
- bar_mask = BAR_MEM_MASK;
- space_base = TSUNAMI_PCI0_MEMORY;
- }
+void
+PciDev::writeConfig(int offset, const uint32_t data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
- // Writing 0xffffffff to a BAR tells the card to set the
- // value of the bar to size of memory it needs
- if (letoh(data32) == 0xffffffff) {
- // This is I/O Space, bottom two bits are read only
+ DPRINTF(PCIDEV,
+ "write device: %#x function: %#x reg: %#x size: 4 data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, data);
+
+ switch (offset) {
+ case PCI0_BASE_ADDR0:
+ case PCI0_BASE_ADDR1:
+ case PCI0_BASE_ADDR2:
+ case PCI0_BASE_ADDR3:
+ case PCI0_BASE_ADDR4:
+ case PCI0_BASE_ADDR5:
+
+ uint32_t barnum, bar_mask;
+ Addr base_addr, base_size, space_base;
+
+ barnum = BAR_NUMBER(offset);
+
+ if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
+ bar_mask = BAR_IO_MASK;
+ space_base = TSUNAMI_PCI0_IO;
+ } else {
+ bar_mask = BAR_MEM_MASK;
+ space_base = TSUNAMI_PCI0_MEMORY;
+ }
- config.baseAddr[barnum] = letoh(
- (~(BARSize[barnum] - 1) & ~bar_mask) |
- (letoh(config.baseAddr[barnum]) & bar_mask));
- } else {
- MemoryController *mmu = params()->mmu;
+ // Writing 0xffffffff to a BAR tells the card to set the
+ // value of the bar to size of memory it needs
+ if (letoh(data) == 0xffffffff) {
+ // This is I/O Space, bottom two bits are read only
- config.baseAddr[barnum] = letoh(
- (letoh(data32) & ~bar_mask) |
+ config.baseAddr[barnum] = letoh(
+ (~(BARSize[barnum] - 1) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
+ } else {
+ config.baseAddr[barnum] = letoh(
+ (letoh(data) & ~bar_mask) |
+ (letoh(config.baseAddr[barnum]) & bar_mask));
+
+ if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
+ base_addr = (letoh(data) & ~bar_mask) + space_base;
+ base_size = BARSize[barnum];
+ BARAddrs[barnum] = base_addr;
- if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
- base_addr = (letoh(data32) & ~bar_mask) + space_base;
- base_size = BARSize[barnum];
-
- // It's never been set
- if (BARAddrs[barnum] == 0)
- mmu->add_child((FunctionalMemory *)this,
- RangeSize(base_addr, base_size));
- else
- mmu->update_child((FunctionalMemory *)this,
- RangeSize(BARAddrs[barnum], base_size),
- RangeSize(base_addr, base_size));
-
- BARAddrs[barnum] = base_addr;
- }
+ pioPort->sendStatusChange(Port::RangeChange);
}
- break;
-
- case PCI0_ROM_BASE_ADDR:
- if (letoh(data32) == 0xfffffffe)
- config.expansionROM = htole((uint32_t)0xffffffff);
- else
- config.expansionROM = data32;
- break;
-
- case PCI_COMMAND:
- // This could also clear some of the error bits in the Status
- // register. However they should never get set, so lets ignore
- // it for now
- config.command = data16;
- break;
-
- default:
- DPRINTF(PCIDEV, "Writing to a read only register");
}
break;
+ case PCI0_ROM_BASE_ADDR:
+ if (letoh(data) == 0xfffffffe)
+ config.expansionROM = htole((uint32_t)0xffffffff);
+ else
+ config.expansionROM = data;
+ break;
+
+ case PCI_COMMAND:
+ // This could also clear some of the error bits in the Status
+ // register. However they should never get set, so lets ignore
+ // it for now
+ config.command = data;
+ break;
+
default:
- panic("invalid access size");
+ DPRINTF(PCIDEV, "Writing to a read only register");
}
}
@@ -296,12 +262,6 @@ PciDev::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
UNSERIALIZE_ARRAY(config.data,
sizeof(config.data) / sizeof(config.data[0]));
-
- // Add the MMU mappings for the BARs
- for (int i=0; i < 6; i++) {
- if (BARAddrs[i] != 0)
- params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i]));
- }
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index bdfc6b932..fc4773908 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -44,7 +44,6 @@
#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
class PciConfigAll;
-class MemoryController;
/**
@@ -85,12 +84,8 @@ class PciConfigData : public SimObject
class PciDev : public DmaDevice
{
public:
- struct Params
+ struct Params : public ::PioDevice::Params
{
- std::string name;
- Platform *plat;
- MemoryController *mmu;
-
/**
* A pointer to the configspace all object that calls us when
* a read comes to this particular device/function.
@@ -111,13 +106,13 @@ class PciDev : public DmaDevice
/** The function number */
uint32_t functionNum;
- };
- protected:
- Params *_params;
+ /** The latency for pio accesses. */
+ Tick pio_delay;
+ };
public:
- const Params *params() const { return _params; }
+ const Params *params() const { return (const Params *)_params; }
protected:
/** The current config space. Unlike the PciConfigData this is
@@ -164,6 +159,7 @@ class PciDev : public DmaDevice
protected:
Platform *plat;
PciConfigData *configData;
+ Tick pioDelay;
public:
Addr pciToDma(Addr pciAddr) const
@@ -181,7 +177,11 @@ class PciDev : public DmaDevice
interruptLine()
{ return configData->config.interruptLine; }
- public:
+ /** return the address ranges that this device responds to.
+ * @params range_list range list to populate with ranges
+ */
+ void addressRanges(AddrRangeList &range_list);
+
/**
* Constructor for PCI Dev. This function copies data from the
* config file object PCIConfigData and registers the device with
@@ -189,39 +189,6 @@ class PciDev : public DmaDevice
*/
PciDev(Params *params);
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
-
- public:
- /**
- * Implement the read/write as BAR accesses
- */
- Fault readBar(MemReqPtr &req, uint8_t *data);
- Fault writeBar(MemReqPtr &req, const uint8_t *data);
-
- public:
- /**
- * Read from a specific BAR
- */
- virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data);
- virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data);
-
- public:
- /**
- * Write to a specific BAR
- */
- virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data);
- virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data);
-
- public:
/**
* Write to the PCI config space data that is stored locally. This may be
* overridden by the device but at some point it will eventually call this
@@ -230,7 +197,9 @@ class PciDev : public DmaDevice
* @param size the size of the write
* @param data the data to write
*/
- virtual void writeConfig(int offset, int size, const uint8_t* data);
+ virtual void writeConfig(int offset, const uint8_t data);
+ virtual void writeConfig(int offset, const uint16_t data);
+ virtual void writeConfig(int offset, const uint32_t data);
/**
@@ -241,7 +210,9 @@ class PciDev : public DmaDevice
* @param size the size of the read
* @param data pointer to the location where the read value should be stored
*/
- virtual void readConfig(int offset, int size, uint8_t *data);
+ virtual void readConfig(int offset, uint8_t *data);
+ virtual void readConfig(int offset, uint16_t *data);
+ virtual void readConfig(int offset, uint32_t *data);
/**
* Serialize this object to the given output stream.
@@ -256,43 +227,4 @@ class PciDev : public DmaDevice
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
-
-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))
- return readBar1(req, req->paddr - BARAddrs[1], data);
- if (isBAR(req->paddr, 2))
- return readBar2(req, req->paddr - BARAddrs[2], data);
- if (isBAR(req->paddr, 3))
- return readBar3(req, req->paddr - BARAddrs[3], data);
- if (isBAR(req->paddr, 4))
- return readBar4(req, req->paddr - BARAddrs[4], data);
- if (isBAR(req->paddr, 5))
- return readBar5(req, req->paddr - BARAddrs[5], data);
- 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))
- return writeBar1(req, req->paddr - BARAddrs[1], data);
- if (isBAR(req->paddr, 2))
- return writeBar2(req, req->paddr - BARAddrs[2], data);
- if (isBAR(req->paddr, 3))
- return writeBar3(req, req->paddr - BARAddrs[3], data);
- if (isBAR(req->paddr, 4))
- return writeBar4(req, req->paddr - BARAddrs[4], data);
- if (isBAR(req->paddr, 5))
- return writeBar5(req, req->paddr - BARAddrs[5], data);
- return genMachineCheckFault();
-}
-
#endif // __DEV_PCIDEV_HH__
diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc
index 639009be9..922a66912 100644
--- a/dev/pktfifo.cc
+++ b/dev/pktfifo.cc
@@ -38,8 +38,8 @@ PacketFifo::copyout(void *dest, int offset, int len)
if (offset + len >= size())
return false;
- list<PacketPtr>::iterator p = fifo.begin();
- list<PacketPtr>::iterator end = fifo.end();
+ list<EthPacketPtr>::iterator p = fifo.begin();
+ list<EthPacketPtr>::iterator end = fifo.end();
while (len > 0) {
while (offset >= (*p)->length) {
offset -= (*p)->length;
@@ -70,8 +70,8 @@ PacketFifo::serialize(const string &base, ostream &os)
paramOut(os, base + ".packets", fifo.size());
int i = 0;
- list<PacketPtr>::iterator p = fifo.begin();
- list<PacketPtr>::iterator end = fifo.end();
+ list<EthPacketPtr>::iterator p = fifo.begin();
+ list<EthPacketPtr>::iterator end = fifo.end();
while (p != end) {
(*p)->serialize(csprintf("%s.packet%d", base, i), os);
++p;
@@ -92,7 +92,7 @@ PacketFifo::unserialize(const string &base, Checkpoint *cp,
fifo.clear();
for (int i = 0; i < fifosize; ++i) {
- PacketPtr p = new PacketData(16384);
+ EthPacketPtr p = new EthPacketData(16384);
p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
fifo.push_back(p);
}
diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh
index e245840a8..336da22d8 100644
--- a/dev/pktfifo.hh
+++ b/dev/pktfifo.hh
@@ -40,11 +40,11 @@ class Checkpoint;
class PacketFifo
{
public:
- typedef std::list<PacketPtr> fifo_list;
+ typedef std::list<EthPacketPtr> fifo_list;
typedef fifo_list::iterator iterator;
protected:
- std::list<PacketPtr> fifo;
+ std::list<EthPacketPtr> fifo;
int _maxsize;
int _size;
int _reserved;
@@ -71,9 +71,9 @@ class PacketFifo
iterator begin() { return fifo.begin(); }
iterator end() { return fifo.end(); }
- PacketPtr front() { return fifo.front(); }
+ EthPacketPtr front() { return fifo.front(); }
- bool push(PacketPtr ptr)
+ bool push(EthPacketPtr ptr)
{
assert(ptr->length);
assert(_reserved <= ptr->length);
@@ -92,7 +92,7 @@ class PacketFifo
if (empty())
return;
- PacketPtr &packet = fifo.front();
+ EthPacketPtr &packet = fifo.front();
_size -= packet->length;
_size -= packet->slack;
packet->slack = 0;
@@ -111,7 +111,7 @@ class PacketFifo
void remove(iterator i)
{
- PacketPtr &packet = *i;
+ EthPacketPtr &packet = *i;
if (i != fifo.begin()) {
iterator prev = i;
--prev;
diff --git a/dev/platform.cc b/dev/platform.cc
index 5b667b12c..9d10e0828 100644
--- a/dev/platform.cc
+++ b/dev/platform.cc
@@ -33,8 +33,8 @@
using namespace std;
using namespace TheISA;
-Platform::Platform(const string &name, IntrControl *intctrl, PciConfigAll *pci)
- : SimObject(name), intrctrl(intctrl), pciconfig(pci)
+Platform::Platform(const string &name, IntrControl *intctrl)
+ : SimObject(name), intrctrl(intctrl)
{
}
diff --git a/dev/platform.hh b/dev/platform.hh
index 1ee645454..f149ca2fb 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -41,6 +41,7 @@ class PciConfigAll;
class IntrControl;
class SimConsole;
class Uart;
+class System;
class Platform : public SimObject
{
@@ -54,9 +55,13 @@ class Platform : public SimObject
/** Pointer to the UART, set by the uart */
Uart *uart;
+ /** Pointer to the system for info about the memory system. */
+ System *system;
+
public:
- Platform(const std::string &name, IntrControl *intctrl, PciConfigAll *pci);
+ Platform(const std::string &name, IntrControl *intctrl);
virtual ~Platform();
+ virtual void init() { if (pciconfig == NULL) panic("PCI Config not set"); }
virtual void postConsoleInt() = 0;
virtual void clearConsoleInt() = 0;
virtual Tick intrFrequency() = 0;
diff --git a/dev/simconsole.cc b/dev/simconsole.cc
index b818e61f4..c3e4f554a 100644
--- a/dev/simconsole.cc
+++ b/dev/simconsole.cc
@@ -49,7 +49,6 @@
#include "dev/platform.hh"
#include "dev/simconsole.hh"
#include "dev/uart.hh"
-#include "mem/functional/memory_control.hh"
#include "sim/builder.hh"
using namespace std;
diff --git a/dev/simple_disk.cc b/dev/simple_disk.cc
index b8c5d44ab..9eee4668c 100644
--- a/dev/simple_disk.cc
+++ b/dev/simple_disk.cc
@@ -42,14 +42,14 @@
#include "base/trace.hh"
#include "dev/disk_image.hh"
#include "dev/simple_disk.hh"
-#include "mem/functional/physical.hh"
+#include "mem/port.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
using namespace std;
-SimpleDisk::SimpleDisk(const string &name, PhysicalMemory *pmem,
- DiskImage *img)
- : SimObject(name), physmem(pmem), image(img)
+SimpleDisk::SimpleDisk(const string &name, System *sys, DiskImage *img)
+ : SimObject(name), system(sys), image(img)
{}
SimpleDisk::~SimpleDisk()
@@ -59,9 +59,7 @@ SimpleDisk::~SimpleDisk()
void
SimpleDisk::read(Addr addr, baddr_t block, int count) const
{
- uint8_t *data = physmem->dma_addr(addr, count);
- if (!data)
- panic("dma out of range! read addr=%#x count=%d\n", addr, count);
+ uint8_t *data = new uint8_t[SectorSize * count];
if (count & (SectorSize - 1))
panic("Not reading a multiple of a sector (count = %d)", count);
@@ -69,8 +67,12 @@ SimpleDisk::read(Addr addr, baddr_t block, int count) const
for (int i = 0, j = 0; i < count; i += SectorSize, j++)
image->read(data + i, block + j);
+ system->functionalPort.writeBlob(addr, data, count);
+
DPRINTF(SimpleDisk, "read block=%#x len=%d\n", (uint64_t)block, count);
DDUMP(SimpleDiskData, data, count);
+
+ delete data;
}
void
@@ -89,21 +91,21 @@ SimpleDisk::write(Addr addr, baddr_t block, int count)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
- SimObjectParam<PhysicalMemory *> physmem;
+ SimObjectParam<System *> system;
SimObjectParam<DiskImage *> disk;
END_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
- INIT_PARAM(physmem, "Physical Memory"),
+ INIT_PARAM(system, "System pointer"),
INIT_PARAM(disk, "Disk Image")
END_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
CREATE_SIM_OBJECT(SimpleDisk)
{
- return new SimpleDisk(getInstanceName(), physmem, disk);
+ return new SimpleDisk(getInstanceName(), system, disk);
}
REGISTER_SIM_OBJECT("SimpleDisk", SimpleDisk)
diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh
index 57f81c5a9..19967f208 100644
--- a/dev/simple_disk.hh
+++ b/dev/simple_disk.hh
@@ -37,7 +37,7 @@
#include "arch/isa_traits.hh"
class DiskImage;
-class PhysicalMemory;
+class System;
/*
* Trivial interface to a disk image used by the System Console
@@ -48,11 +48,11 @@ class SimpleDisk : public SimObject
typedef uint64_t baddr_t;
protected:
- PhysicalMemory *physmem;
+ System *system;
DiskImage *image;
public:
- SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img);
+ SimpleDisk(const std::string &name, System *sys, DiskImage *img);
~SimpleDisk();
void read(Addr addr, baddr_t block, int count) const;
diff --git a/dev/sinic.cc b/dev/sinic.cc
index 0853717ba..66ca88dbe 100644
--- a/dev/sinic.cc
+++ b/dev/sinic.cc
@@ -28,6 +28,7 @@
#include <cstdio>
#include <deque>
+#include <limits>
#include <string>
#include "base/inet.hh"
@@ -36,12 +37,7 @@
#include "dev/etherlink.hh"
#include "dev/sinic.hh"
#include "dev/pciconfigall.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/dma_interface.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/eventq.hh"
@@ -87,7 +83,6 @@ Base::Base(Params *p)
Device::Device(Params *p)
: Base(p), plat(p->plat), physmem(p->physmem), rxUnique(0), txUnique(0),
virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),
- rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
rxKickTick(0), txKickTick(0),
txEvent(this), rxDmaEvent(this), txDmaEvent(this),
dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
@@ -95,25 +90,6 @@ Device::Device(Params *p)
{
reset();
- if (p->pio_bus) {
- pioInterface = newPioInterface(p->name + ".pio", p->hier, p->pio_bus,
- this, &Device::cacheAccess);
- pioLatency = p->pio_latency * p->pio_bus->clockRate;
- }
-
- if (p->header_bus) {
- if (p->payload_bus)
- dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
- p->header_bus,
- p->payload_bus, 1,
- p->dma_no_allocate);
- else
- dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
- p->header_bus,
- p->header_bus, 1,
- p->dma_no_allocate);
- } else if (p->payload_bus)
- panic("must define a header bus if defining a payload bus");
}
Device::~Device()
@@ -289,29 +265,6 @@ Device::regStats()
rxPacketRate = rxPackets / simSeconds;
}
-/**
- * This is to write to the PCI general configuration registers
- */
-void
-Device::writeConfig(int offset, int size, const uint8_t *data)
-{
- switch (offset) {
- case PCI0_BASE_ADDR0:
- // Need to catch writes to BARs to update the PIO interface
- PciDev::writeConfig(offset, size, data);
- if (BARAddrs[0] != 0) {
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
-
- BARAddrs[0] &= EV5::PAddrUncachedMask;
- }
- break;
-
- default:
- PciDev::writeConfig(offset, size, data);
- }
-}
-
void
Device::prepareIO(int cpu, int index)
{
@@ -358,76 +311,65 @@ Device::prepareWrite(int cpu, int index)
/**
* I/O read of device register
*/
-Fault
-Device::read(MemReqPtr &req, uint8_t *data)
+Tick
+Device::read(Packet &pkt)
{
assert(config.command & PCI_CMD_MSE);
- Fault fault = readBar(req, data);
-
- if (fault && fault->isMachineCheckFault()) {
- panic("address does not map to a BAR pa=%#x va=%#x size=%d",
- req->paddr, req->vaddr, req->size);
-
- return genMachineCheckFault();
- }
+ assert(pkt.addr >= BARAddrs[0] && pkt.size < BARSize[0]);
- return fault;
-}
-
-Fault
-Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
-{
- int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff;
+ int cpu = pkt.req->getCpuNum();
+ Addr daddr = pkt.addr - BARAddrs[0];
Addr index = daddr >> Regs::VirtualShift;
Addr raddr = daddr & Regs::VirtualMask;
+ pkt.time += pioDelay;
+ pkt.allocate();
+
if (!regValid(raddr))
- panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d",
- cpu, index, daddr, req->paddr, req->vaddr, req->size);
+ panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ cpu, index, daddr, pkt.addr, pkt.size);
const Regs::Info &info = regInfo(raddr);
if (!info.read)
panic("read %s (write only): "
- "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d",
- info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size);
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt.addr, pkt.size);
- if (req->size != info.size)
panic("read %s (invalid size): "
- "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d",
- info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size);
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt.addr, pkt.size);
prepareRead(cpu, index);
uint64_t value = 0;
- if (req->size == 4) {
- uint32_t &reg = *(uint32_t *)data;
- reg = regData32(raddr);
+ if (pkt.size == 4) {
+ uint32_t reg = regData32(raddr);
+ pkt.set(reg);
value = reg;
}
- if (req->size == 8) {
- uint64_t &reg = *(uint64_t *)data;
- reg = regData64(raddr);
+ if (pkt.size == 8) {
+ uint64_t reg = regData64(raddr);
+ pkt.set(reg);
value = reg;
}
DPRINTF(EthernetPIO,
- "read %s: cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d val=%#x\n",
- info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size,
- value);
+ "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
+ info.name, cpu, index, daddr, pkt.addr, pkt.size, value);
// reading the interrupt status register has the side effect of
// clearing it
if (raddr == Regs::IntrStatus)
devIntrClear();
- return NoFault;
+ return pioDelay;
}
/**
* IPR read of device register
- */
-Fault
+
+ Fault
Device::iprRead(Addr daddr, int cpu, uint64_t &result)
{
if (!regValid(daddr))
@@ -453,74 +395,62 @@ Device::iprRead(Addr daddr, int cpu, uint64_t &result)
return NoFault;
}
-
+*/
/**
* I/O write of device register
*/
-Fault
-Device::write(MemReqPtr &req, const uint8_t *data)
+Tick
+Device::write(Packet &pkt)
{
assert(config.command & PCI_CMD_MSE);
- Fault fault = writeBar(req, data);
-
- if (fault && fault->isMachineCheckFault()) {
- panic("address does not map to a BAR pa=%#x va=%#x size=%d",
- req->paddr, req->vaddr, req->size);
+ assert(pkt.addr >= BARAddrs[0] && pkt.size < BARSize[0]);
- return genMachineCheckFault();
- }
-
- return fault;
-}
-
-Fault
-Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{
- int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff;
+ int cpu = pkt.req->getCpuNum();
+ Addr daddr = pkt.addr - BARAddrs[0];
Addr index = daddr >> Regs::VirtualShift;
Addr raddr = daddr & Regs::VirtualMask;
+ pkt.time += pioDelay;
+
if (!regValid(raddr))
- panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d",
- cpu, daddr, req->paddr, req->vaddr, req->size);
+ panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
+ cpu, daddr, pkt.addr, pkt.size);
const Regs::Info &info = regInfo(raddr);
if (!info.write)
panic("write %s (read only): "
- "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d",
- info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size);
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt.addr, pkt.size);
- if (req->size != info.size)
+ if (pkt.size != info.size)
panic("write %s (invalid size): "
- "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d",
- info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size);
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt.addr, pkt.size);
- uint32_t reg32 = *(uint32_t *)data;
- uint64_t reg64 = *(uint64_t *)data;
VirtualReg &vnic = virtualRegs[index];
DPRINTF(EthernetPIO,
- "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n",
- info.name, index, cpu, info.size == 4 ? reg32 : reg64, daddr,
- req->paddr, req->vaddr, req->size);
+ "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
+ info.name, index, cpu, info.size == 4 ? pkt.get<uint32_t>() :
+ pkt.get<uint64_t>(), daddr, pkt.addr, pkt.size);
prepareWrite(cpu, index);
switch (raddr) {
case Regs::Config:
- changeConfig(reg32);
+ changeConfig(pkt.get<uint32_t>());
break;
case Regs::Command:
- command(reg32);
+ command(pkt.get<uint32_t>());
break;
case Regs::IntrStatus:
- devIntrClear(regs.IntrStatus & reg32);
+ devIntrClear(regs.IntrStatus & pkt.get<uint32_t>());
break;
case Regs::IntrMask:
- devIntrChangeMask(reg32);
+ devIntrChangeMask(pkt.get<uint32_t>());
break;
case Regs::RxData:
@@ -530,7 +460,7 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
vnic.rxUnique = rxUnique++;
vnic.RxDone = Regs::RxDone_Busy;
- vnic.RxData = reg64;
+ vnic.RxData = pkt.get<uint64_t>();
if (Regs::get_RxData_Vaddr(reg64)) {
Addr vaddr = Regs::get_RxData_Addr(reg64);
@@ -566,16 +496,16 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
vnic.txUnique = txUnique++;
vnic.TxDone = Regs::TxDone_Busy;
- vnic.TxData = reg64;
- if (Regs::get_TxData_Vaddr(reg64)) {
- Addr vaddr = Regs::get_TxData_Addr(reg64);
+ if (Regs::get_TxData_Vaddr(pkt.get<uint64_t>())) {
+ panic("vtophys won't work here in newmem.\n");
+ /*Addr vaddr = Regs::get_TxData_Addr(reg64);
Addr paddr = vtophys(req->xc, vaddr);
DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): "
"vaddr=%#x, paddr=%#x\n",
index, vnic.txUnique, vaddr, paddr);
- vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);
+ vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/
} else {
DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",
index, vnic.txUnique);
@@ -590,7 +520,7 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
break;
}
- return NoFault;
+ return pioDelay;
}
void
@@ -850,22 +780,13 @@ Device::reset()
}
void
-Device::rxDmaCopy()
+Device::rxDmaDone()
{
assert(rxState == rxCopy);
rxState = rxCopyDone;
- DPRINTF(EthernetDMA, "begin rx dma write paddr=%#x len=%d\n",
- rxDmaAddr, rxDmaLen);
- physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n",
rxDmaAddr, rxDmaLen);
DDUMP(EthernetData, rxDmaData, rxDmaLen);
-}
-
-void
-Device::rxDmaDone()
-{
- rxDmaCopy();
// If the transmit state machine has a pending DMA, let it go first
if (txState == txBeginCopy)
@@ -1001,34 +922,22 @@ Device::rxKick()
break;
case rxBeginCopy:
- if (dmaInterface && dmaInterface->busy())
+ if (dmaPending())
goto exit;
- rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(vnic->RxData));
- rxDmaLen = min<int>(Regs::get_RxData_Len(vnic->RxData),
+ rxDmaAddr = params()->platform->pciToDma(
+ Regs::get_RxData_Addr(vnic->RxData));
+ rxDmaLen = std::min<int>(Regs::get_RxData_Len(vnic->RxData),
vnic->rxPacketBytes);
rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset;
rxState = rxCopy;
-
if (rxDmaAddr == 1LL) {
rxState = rxCopyDone;
break;
}
- if (dmaInterface) {
- dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
- curTick, &rxDmaEvent, true);
- goto exit;
- }
-
- if (dmaWriteDelay != 0 || dmaWriteFactor != 0) {
- Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
- Tick start = curTick + dmaWriteDelay + factor;
- rxDmaEvent.schedule(start);
- goto exit;
- }
- rxDmaCopy();
+ dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData);
break;
case rxCopy:
@@ -1095,20 +1004,13 @@ Device::rxKick()
}
void
-Device::txDmaCopy()
+Device::txDmaDone()
{
assert(txState == txCopy);
txState = txCopyDone;
- physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
txDmaAddr, txDmaLen);
DDUMP(EthernetData, txDmaData, txDmaLen);
-}
-
-void
-Device::txDmaDone()
-{
- txDmaCopy();
// If the receive state machine has a pending DMA, let it go first
if (rxState == rxBeginCopy)
@@ -1126,7 +1028,7 @@ Device::transmit()
}
uint32_t interrupts;
- PacketPtr packet = txFifo.front();
+ EthPacketPtr packet = txFifo.front();
if (!interface->sendPacket(packet)) {
DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
txFifo.avail());
@@ -1194,7 +1096,7 @@ Device::txKick()
assert(Regs::get_TxDone_Busy(vnic->TxDone));
if (!txPacket) {
// Grab a new packet from the fifo.
- txPacket = new PacketData(16384);
+ txPacket = new EthPacketData(16384);
txPacketOffset = 0;
}
@@ -1208,28 +1110,16 @@ Device::txKick()
break;
case txBeginCopy:
- if (dmaInterface && dmaInterface->busy())
+ if (dmaPending())
goto exit;
- txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(vnic->TxData));
+ txDmaAddr = params()->platform->pciToDma(
+ Regs::get_TxData_Addr(vnic->TxData));
txDmaLen = Regs::get_TxData_Len(vnic->TxData);
txDmaData = txPacket->data + txPacketOffset;
txState = txCopy;
- if (dmaInterface) {
- dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
- curTick, &txDmaEvent, true);
- goto exit;
- }
-
- if (dmaReadDelay != 0 || dmaReadFactor != 0) {
- Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
- Tick start = curTick + dmaReadDelay + factor;
- txDmaEvent.schedule(start);
- goto exit;
- }
-
- txDmaCopy();
+ dmaRead(txDmaAddr, txDmaLen, &txDmaEvent, txDmaData);
break;
case txCopy:
@@ -1316,7 +1206,7 @@ Device::transferDone()
}
bool
-Device::rxFilter(const PacketPtr &packet)
+Device::rxFilter(const EthPacketPtr &packet)
{
if (!Regs::get_Config_Filter(regs.Config))
return false;
@@ -1361,7 +1251,7 @@ Device::rxFilter(const PacketPtr &packet)
}
bool
-Device::recvPacket(PacketPtr packet)
+Device::recvPacket(EthPacketPtr packet)
{
rxBytes += packet->length;
rxPackets++;
@@ -1402,7 +1292,7 @@ Device::recvPacket(PacketPtr packet)
//
//
void
-Base::serialize(ostream &os)
+Base::serialize(std::ostream &os)
{
// Serialize the PciDev base class
PciDev::serialize(os);
@@ -1446,7 +1336,7 @@ Base::unserialize(Checkpoint *cp, const std::string &section)
}
void
-Device::serialize(ostream &os)
+Device::serialize(std::ostream &os)
{
int count;
@@ -1484,7 +1374,7 @@ Device::serialize(ostream &os)
for (int i = 0; i < virtualRegsSize; ++i) {
VirtualReg *vnic = &virtualRegs[i];
- string reg = csprintf("vnic%d", i);
+ std::string reg = csprintf("vnic%d", i);
paramOut(os, reg + ".RxData", vnic->RxData);
paramOut(os, reg + ".RxDone", vnic->RxDone);
paramOut(os, reg + ".TxData", vnic->TxData);
@@ -1639,7 +1529,7 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(txPacketExists);
txPacket = 0;
if (txPacketExists) {
- txPacket = new PacketData(16384);
+ txPacket = new EthPacketData(16384);
txPacket->unserialize("txPacket", cp, section);
UNSERIALIZE_SCALAR(txPacketOffset);
UNSERIALIZE_SCALAR(txPacketBytes);
@@ -1657,7 +1547,7 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
virtualRegs.resize(virtualRegsSize);
for (int i = 0; i < virtualRegsSize; ++i) {
VirtualReg *vnic = &virtualRegs[i];
- string reg = csprintf("vnic%d", i);
+ std::string reg = csprintf("vnic%d", i);
paramIn(cp, section, reg + ".RxData", vnic->RxData);
paramIn(cp, section, reg + ".RxDone", vnic->RxDone);
@@ -1693,28 +1583,11 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
if (transmitTick)
txEvent.schedule(curTick + transmitTick);
- /*
- * re-add addrRanges to bus bridges
- */
- if (pioInterface)
- pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
-}
-
-Tick
-Device::cacheAccess(MemReqPtr &req)
-{
- Addr daddr;
- int bar;
- if (!getBAR(req->paddr, daddr, bar))
- panic("address does not map to a BAR pa=%#x va=%#x size=%d",
- req->paddr, req->vaddr, req->size);
+ pioPort->sendStatusChange(Port::RangeChange);
- DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n",
- req->cmd.toString(), req->paddr, bar, daddr);
-
- return curTick + pioLatency;
}
+
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
SimObjectParam<EtherInt *> peer;
@@ -1747,29 +1620,22 @@ REGISTER_SIM_OBJECT("SinicInt", Interface)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
- Param<Tick> clock;
- Param<Addr> addr;
- SimObjectParam<MemoryController *> mmu;
- SimObjectParam<PhysicalMemory *> physmem;
+ SimObjectParam<System *> system;
+ SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
+ Param<Tick> pio_latency;
+ Param<Tick> intr_delay;
- SimObjectParam<HierParams *> hier;
- SimObjectParam<Bus*> pio_bus;
- SimObjectParam<Bus*> dma_bus;
- SimObjectParam<Bus*> payload_bus;
+ Param<Tick> clock;
Param<Tick> dma_read_delay;
Param<Tick> dma_read_factor;
Param<Tick> dma_write_delay;
Param<Tick> dma_write_factor;
- Param<bool> dma_no_allocate;
- Param<Tick> pio_latency;
- Param<Tick> intr_delay;
Param<Tick> rx_delay;
Param<Tick> tx_delay;
@@ -1784,7 +1650,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
Param<uint32_t> tx_fifo_threshold;
Param<bool> rx_filter;
- Param<string> hardware_address;
+ Param<std::string> hardware_address;
Param<bool> rx_thread;
Param<bool> tx_thread;
Param<bool> rss;
@@ -1797,29 +1663,22 @@ END_DECLARE_SIM_OBJECT_PARAMS(Device)
BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
- INIT_PARAM(clock, "State machine cycle time"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(physmem, "Physical Memory"),
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(platform, "Platform"),
- INIT_PARAM(pci_bus, "PCI bus"),
+ INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(intr_delay, "Interrupt Delay"),
+ INIT_PARAM(clock, "State machine cycle time"),
- INIT_PARAM(hier, "Hierarchy global variables"),
- INIT_PARAM(pio_bus, ""),
- INIT_PARAM(dma_bus, ""),
- INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"),
INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
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(intr_delay, "Interrupt Delay"),
INIT_PARAM(rx_delay, "Receive Delay"),
INIT_PARAM(tx_delay, "Transmit Delay"),
@@ -1849,31 +1708,22 @@ END_INIT_SIM_OBJECT_PARAMS(Device)
CREATE_SIM_OBJECT(Device)
{
Device::Params *params = new Device::Params;
-
params->name = getInstanceName();
-
- params->clock = clock;
-
- params->mmu = mmu;
- params->physmem = physmem;
+ params->platform = platform;
+ params->system = system;
params->configSpace = configspace;
params->configData = configdata;
- params->plat = platform;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
params->functionNum = pci_func;
+ params->pio_delay = pio_latency;
+ params->intr_delay = intr_delay;
+ params->clock = clock;
- params->hier = hier;
- params->pio_bus = pio_bus;
- params->header_bus = dma_bus;
- params->payload_bus = payload_bus;
params->dma_read_delay = dma_read_delay;
params->dma_read_factor = dma_read_factor;
params->dma_write_delay = dma_write_delay;
params->dma_write_factor = dma_write_factor;
- params->dma_no_allocate = dma_no_allocate;
- params->pio_latency = pio_latency;
- params->intr_delay = intr_delay;
params->tx_delay = tx_delay;
params->rx_delay = rx_delay;
diff --git a/dev/sinic.hh b/dev/sinic.hh
index 892b3ab69..a786c3e44 100644
--- a/dev/sinic.hh
+++ b/dev/sinic.hh
@@ -37,7 +37,6 @@
#include "dev/pcidev.hh"
#include "dev/pktfifo.hh"
#include "dev/sinicreg.hh"
-#include "mem/bus/bus.hh"
#include "sim/eventq.hh"
namespace Sinic {
@@ -91,10 +90,6 @@ class Base : public PciDev
class Device : public Base
{
protected:
- Platform *plat;
- PhysicalMemory *physmem;
-
- protected:
/** Receive State Machine States */
enum RxState {
rxIdle,
@@ -169,10 +164,6 @@ class Device : public Base
uint32_t &regData32(Addr daddr) { return *(uint32_t *)&regData8(daddr); }
uint64_t &regData64(Addr daddr) { return *(uint64_t *)&regData8(daddr); }
- private:
- Addr addr;
- static const Addr size = Regs::Size;
-
protected:
RxState rxState;
PacketFifo rxFifo;
@@ -186,7 +177,7 @@ class Device : public Base
TxState txState;
PacketFifo txFifo;
bool txFull;
- PacketPtr txPacket;
+ EthPacketPtr txPacket;
int txPacketOffset;
int txPacketBytes;
Addr txDmaAddr;
@@ -226,7 +217,7 @@ class Device : public Base
/**
* receive address filter
*/
- bool rxFilter(const PacketPtr &packet);
+ bool rxFilter(const EthPacketPtr &packet);
/**
* device configuration
@@ -238,7 +229,7 @@ class Device : public Base
* device ethernet interface
*/
public:
- bool recvPacket(PacketPtr packet);
+ bool recvPacket(EthPacketPtr packet);
void transferDone();
void setInterface(Interface *i) { assert(!interface); interface = i; }
@@ -246,12 +237,10 @@ class Device : public Base
* DMA parameters
*/
protected:
- void rxDmaCopy();
void rxDmaDone();
friend class EventWrapper<Device, &Device::rxDmaDone>;
EventWrapper<Device, &Device::rxDmaDone> rxDmaEvent;
- void txDmaCopy();
void txDmaDone();
friend class EventWrapper<Device, &Device::txDmaDone>;
EventWrapper<Device, &Device::txDmaDone> txDmaEvent;
@@ -270,25 +259,16 @@ class Device : public Base
void devIntrChangeMask(uint32_t newmask);
/**
- * PCI Configuration interface
- */
- public:
- virtual void writeConfig(int offset, int size, const uint8_t *data);
-
-/**
* Memory Interface
*/
public:
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
void prepareIO(int cpu, int index);
void prepareRead(int cpu, int index);
void prepareWrite(int cpu, int index);
- Fault iprRead(Addr daddr, int cpu, uint64_t &result);
- Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
- Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
- Tick cacheAccess(MemReqPtr &req);
+ // Fault iprRead(Addr daddr, int cpu, uint64_t &result);
/**
* Statistics
@@ -336,17 +316,8 @@ class Device : public Base
public:
struct Params : public Base::Params
{
- IntrControl *i;
- PhysicalMemory *pmem;
Tick tx_delay;
Tick rx_delay;
- HierParams *hier;
- Bus *pio_bus;
- Bus *header_bus;
- Bus *payload_bus;
- Tick pio_latency;
- PhysicalMemory *physmem;
- IntrControl *intctrl;
bool rx_filter;
Net::EthAddr eaddr;
uint32_t rx_max_copy;
@@ -362,7 +333,6 @@ class Device : public Base
Tick dma_read_factor;
Tick dma_write_delay;
Tick dma_write_factor;
- bool dma_no_allocate;
bool rx_thread;
bool tx_thread;
bool rss;
@@ -392,7 +362,7 @@ class Interface : public EtherInt
Interface(const std::string &name, Device *d)
: EtherInt(name), dev(d) { dev->setInterface(this); }
- virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
+ virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); }
};
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index 58fc7434e..ed011531d 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -36,12 +36,10 @@
#include "cpu/intr_control.hh"
#include "dev/simconsole.hh"
-#include "dev/ide_ctrl.hh"
#include "dev/tsunami_cchip.hh"
#include "dev/tsunami_pchip.hh"
#include "dev/tsunami_io.hh"
#include "dev/tsunami.hh"
-#include "dev/pciconfigall.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
@@ -49,9 +47,8 @@ using namespace std;
//Should this be AlphaISA?
using namespace TheISA;
-Tsunami::Tsunami(const string &name, System *s, IntrControl *ic,
- PciConfigAll *pci)
- : Platform(name, ic, pci), system(s)
+Tsunami::Tsunami(const string &name, System *s, IntrControl *ic)
+ : Platform(name, ic), system(s)
{
// set the back pointer from the system to myself
system->platform = this;
@@ -112,21 +109,19 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
SimObjectParam<System *> system;
SimObjectParam<IntrControl *> intrctrl;
- SimObjectParam<PciConfigAll *> pciconfig;
END_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami)
INIT_PARAM(system, "system"),
- INIT_PARAM(intrctrl, "interrupt controller"),
- INIT_PARAM(pciconfig, "PCI configuration")
+ INIT_PARAM(intrctrl, "interrupt controller")
END_INIT_SIM_OBJECT_PARAMS(Tsunami)
CREATE_SIM_OBJECT(Tsunami)
{
- return new Tsunami(getInstanceName(), system, intrctrl, pciconfig);
+ return new Tsunami(getInstanceName(), system, intrctrl);
}
REGISTER_SIM_OBJECT("Tsunami", Tsunami)
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
index 7fd91d5b2..668c82674 100644
--- a/dev/tsunami.hh
+++ b/dev/tsunami.hh
@@ -38,12 +38,9 @@
#include "dev/platform.hh"
class IdeController;
-class TlaserClock;
-class NSGigE;
class TsunamiCChip;
class TsunamiPChip;
class TsunamiIO;
-class PciConfigAll;
class System;
/**
@@ -86,8 +83,7 @@ class Tsunami : public Platform
* @param name name of the object
* @param intrctrl pointer to the interrupt controller
*/
- Tsunami(const std::string &name, System *s, IntrControl *intctrl,
- PciConfigAll *pci);
+ Tsunami(const std::string &name, System *s, IntrControl *intctrl);
/**
* Return the interrupting frequency to AlphaAccess
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index 2649fe27a..7b9032f6e 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -34,14 +34,12 @@
#include <string>
#include <vector>
+#include "arch/alpha/ev5.hh"
#include "base/trace.hh"
#include "dev/tsunami_cchip.hh"
#include "dev/tsunamireg.h"
#include "dev/tsunami.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
+#include "mem/port.hh"
#include "cpu/exec_context.hh"
#include "cpu/intr_control.hh"
#include "sim/builder.hh"
@@ -51,19 +49,10 @@ using namespace std;
//Should this be AlphaISA?
using namespace TheISA;
-TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier,
- Bus* pio_bus, Tick pio_latency)
- : PioDevice(name, t), addr(a), tsunami(t)
+TsunamiCChip::TsunamiCChip(Params *p)
+ : BasicPioDevice(p), tsunami(p->tsunami)
{
- mmu->add_child(this, RangeSize(addr, size));
-
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &TsunamiCChip::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- pioLatency = pio_latency * pio_bus->clockRate;
- }
+ pioSize = 0xfffffff;
drir = 0;
ipint = 0;
@@ -79,315 +68,302 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
tsunami->cchip = this;
}
-Fault
-TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
+Tick
+TsunamiCChip::read(Packet &pkt)
{
- DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size);
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size);
- Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
- ExecContext *xc = req->xc;
+ pkt.time += pioDelay;
+ Addr regnum = (pkt.addr - pioAddr) >> 6;
+ Addr daddr = (pkt.addr - pioAddr);
- switch (req->size) {
+ pkt.allocate();
+ switch (pkt.size) {
case sizeof(uint64_t):
if (daddr & TSDEV_CC_BDIMS)
{
- *(uint64_t*)data = dim[(daddr >> 4) & 0x3F];
- return NoFault;
+ pkt.set(dim[(daddr >> 4) & 0x3F]);
+ break;
}
if (daddr & TSDEV_CC_BDIRS)
{
- *(uint64_t*)data = dir[(daddr >> 4) & 0x3F];
- return NoFault;
+ pkt.set(dir[(daddr >> 4) & 0x3F]);
+ break;
}
switch(regnum) {
case TSDEV_CC_CSR:
- *(uint64_t*)data = 0x0;
- return NoFault;
+ pkt.set(0x0);
+ break;
case TSDEV_CC_MTR:
panic("TSDEV_CC_MTR not implemeted\n");
- return NoFault;
+ break;
case TSDEV_CC_MISC:
- *(uint64_t*)data = (ipint << 8) & 0xF |
- (itint << 4) & 0xF |
- (xc->readCpuId() & 0x3);
- return NoFault;
+ pkt.set((ipint << 8) & 0xF | (itint << 4) & 0xF |
+ (pkt.req->getCpuNum() & 0x3));
+ break;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
case TSDEV_CC_AAR2:
case TSDEV_CC_AAR3:
- *(uint64_t*)data = 0;
- return NoFault;
+ pkt.set(0);
+ break;
case TSDEV_CC_DIM0:
- *(uint64_t*)data = dim[0];
- return NoFault;
+ pkt.set(dim[0]);
+ break;
case TSDEV_CC_DIM1:
- *(uint64_t*)data = dim[1];
- return NoFault;
+ pkt.set(dim[1]);
+ break;
case TSDEV_CC_DIM2:
- *(uint64_t*)data = dim[2];
- return NoFault;
+ pkt.set(dim[2]);
+ break;
case TSDEV_CC_DIM3:
- *(uint64_t*)data = dim[3];
- return NoFault;
+ pkt.set(dim[3]);
+ break;
case TSDEV_CC_DIR0:
- *(uint64_t*)data = dir[0];
- return NoFault;
+ pkt.set(dir[0]);
+ break;
case TSDEV_CC_DIR1:
- *(uint64_t*)data = dir[1];
- return NoFault;
+ pkt.set(dir[1]);
+ break;
case TSDEV_CC_DIR2:
- *(uint64_t*)data = dir[2];
- return NoFault;
+ pkt.set(dir[2]);
+ break;
case TSDEV_CC_DIR3:
- *(uint64_t*)data = dir[3];
- return NoFault;
+ pkt.set(dir[3]);
+ break;
case TSDEV_CC_DRIR:
- *(uint64_t*)data = drir;
- return NoFault;
+ pkt.set(drir);
+ break;
case TSDEV_CC_PRBEN:
panic("TSDEV_CC_PRBEN not implemented\n");
- return NoFault;
+ break;
case TSDEV_CC_IIC0:
case TSDEV_CC_IIC1:
case TSDEV_CC_IIC2:
case TSDEV_CC_IIC3:
panic("TSDEV_CC_IICx not implemented\n");
- return NoFault;
+ break;
case TSDEV_CC_MPR0:
case TSDEV_CC_MPR1:
case TSDEV_CC_MPR2:
case TSDEV_CC_MPR3:
panic("TSDEV_CC_MPRx not implemented\n");
- return NoFault;
+ break;
case TSDEV_CC_IPIR:
- *(uint64_t*)data = ipint;
- return NoFault;
+ pkt.set(ipint);
+ break;
case TSDEV_CC_ITIR:
- *(uint64_t*)data = itint;
- return NoFault;
+ pkt.set(itint);
+ break;
default:
panic("default in cchip read reached, accessing 0x%x\n");
} // uint64_t
break;
case sizeof(uint32_t):
- if (regnum == TSDEV_CC_DRIR) {
- warn("accessing DRIR with 32 bit read, "
- "hopefully your just reading this for timing");
- *(uint32_t*)data = drir;
- } else
- panic("invalid access size(?) for tsunami register!\n");
- return NoFault;
case sizeof(uint16_t):
case sizeof(uint8_t):
default:
panic("invalid access size(?) for tsunami register!\n");
}
- DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size);
+ DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
+ regnum, pkt.size, pkt.get<uint64_t>());
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
-Fault
-TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
+Tick
+TsunamiCChip::write(Packet &pkt)
{
- DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
- req->vaddr, *(uint64_t*)data, req->size);
+ pkt.time += pioDelay;
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
- Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
- bool supportedWrite = false;
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ Addr daddr = pkt.addr - pioAddr;
+ Addr regnum = (pkt.addr - pioAddr) >> 6 ;
- switch (req->size) {
- case sizeof(uint64_t):
- if (daddr & TSDEV_CC_BDIMS)
- {
- int number = (daddr >> 4) & 0x3F;
-
- uint64_t bitvector;
- uint64_t olddim;
- uint64_t olddir;
-
- olddim = dim[number];
- olddir = dir[number];
- dim[number] = *(uint64_t*)data;
- dir[number] = dim[number] & drir;
- for(int x = 0; x < Tsunami::Max_CPUs; x++)
- {
- bitvector = ULL(1) << x;
- // Figure out which bits have changed
- if ((dim[number] & bitvector) != (olddim & bitvector))
- {
- // The bit is now set and it wasn't before (set)
- if((dim[number] & bitvector) && (dir[number] & bitvector))
- {
- tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
- DPRINTF(Tsunami, "dim write resulting in posting dir"
- " interrupt to cpu %d\n", number);
- }
- else if ((olddir & bitvector) &&
- !(dir[number] & bitvector))
- {
- // The bit was set and now its now clear and
- // we were interrupting on that bit before
- tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
- DPRINTF(Tsunami, "dim write resulting in clear"
- " dir interrupt to cpu %d\n", number);
+ assert(pkt.size == sizeof(uint64_t));
- }
+ DPRINTF(Tsunami, "write - addr=%#x value=%#x\n", pkt.addr, pkt.get<uint64_t>());
+ bool supportedWrite = false;
- }
- }
- return NoFault;
- }
- switch(regnum) {
- case TSDEV_CC_CSR:
- panic("TSDEV_CC_CSR write\n");
- return NoFault;
- case TSDEV_CC_MTR:
- panic("TSDEV_CC_MTR write not implemented\n");
- return NoFault;
- case TSDEV_CC_MISC:
- uint64_t ipreq;
- ipreq = (*(uint64_t*)data >> 12) & 0xF;
- //If it is bit 12-15, this is an IPI post
- if (ipreq) {
- reqIPI(ipreq);
- supportedWrite = true;
+ if (daddr & TSDEV_CC_BDIMS)
+ {
+ int number = (daddr >> 4) & 0x3F;
+
+ uint64_t bitvector;
+ uint64_t olddim;
+ uint64_t olddir;
+
+ olddim = dim[number];
+ olddir = dir[number];
+ dim[number] = pkt.get<uint64_t>();
+ dir[number] = dim[number] & drir;
+ for(int x = 0; x < Tsunami::Max_CPUs; x++)
+ {
+ bitvector = ULL(1) << x;
+ // Figure out which bits have changed
+ if ((dim[number] & bitvector) != (olddim & bitvector))
+ {
+ // The bit is now set and it wasn't before (set)
+ if((dim[number] & bitvector) && (dir[number] & bitvector))
+ {
+ tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
+ DPRINTF(Tsunami, "dim write resulting in posting dir"
+ " interrupt to cpu %d\n", number);
}
+ else if ((olddir & bitvector) &&
+ !(dir[number] & bitvector))
+ {
+ // The bit was set and now its now clear and
+ // we were interrupting on that bit before
+ tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
+ DPRINTF(Tsunami, "dim write resulting in clear"
+ " dir interrupt to cpu %d\n", number);
- //If it is bit 8-11, this is an IPI clear
- uint64_t ipintr;
- ipintr = (*(uint64_t*)data >> 8) & 0xF;
- if (ipintr) {
- clearIPI(ipintr);
- supportedWrite = true;
}
- //If it is the 4-7th bit, clear the RTC interrupt
- uint64_t itintr;
- itintr = (*(uint64_t*)data >> 4) & 0xF;
- if (itintr) {
- clearITI(itintr);
- supportedWrite = true;
- }
- // ignore NXMs
- if (*(uint64_t*)data & 0x10000000)
- supportedWrite = true;
+ }
+ }
+ } else {
+ switch(regnum) {
+ case TSDEV_CC_CSR:
+ panic("TSDEV_CC_CSR write\n");
+ case TSDEV_CC_MTR:
+ panic("TSDEV_CC_MTR write not implemented\n");
+ case TSDEV_CC_MISC:
+ uint64_t ipreq;
+ ipreq = (pkt.get<uint64_t>() >> 12) & 0xF;
+ //If it is bit 12-15, this is an IPI post
+ if (ipreq) {
+ reqIPI(ipreq);
+ supportedWrite = true;
+ }
- if(!supportedWrite)
- panic("TSDEV_CC_MISC write not implemented\n");
+ //If it is bit 8-11, this is an IPI clear
+ uint64_t ipintr;
+ ipintr = (pkt.get<uint64_t>() >> 8) & 0xF;
+ if (ipintr) {
+ clearIPI(ipintr);
+ supportedWrite = true;
+ }
- 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 NoFault;
- case TSDEV_CC_DIM0:
- case TSDEV_CC_DIM1:
- case TSDEV_CC_DIM2:
- case TSDEV_CC_DIM3:
- int number;
- if(regnum == TSDEV_CC_DIM0)
- number = 0;
- else if(regnum == TSDEV_CC_DIM1)
- number = 1;
- else if(regnum == TSDEV_CC_DIM2)
- number = 2;
- else
- number = 3;
-
- uint64_t bitvector;
- uint64_t olddim;
- uint64_t olddir;
-
- olddim = dim[number];
- olddir = dir[number];
- dim[number] = *(uint64_t*)data;
- dir[number] = dim[number] & drir;
- for(int x = 0; x < 64; x++)
- {
- bitvector = ULL(1) << x;
- // Figure out which bits have changed
- if ((dim[number] & bitvector) != (olddim & bitvector))
- {
- // The bit is now set and it wasn't before (set)
- if((dim[number] & bitvector) && (dir[number] & bitvector))
- {
- tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
- DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
- }
- else if ((olddir & bitvector) &&
- !(dir[number] & bitvector))
- {
- // The bit was set and now its now clear and
- // we were interrupting on that bit before
- tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
- DPRINTF(Tsunami, "dim write resulting in clear"
- " dir interrupt to cpu %d\n",
- x);
-
- }
-
-
- }
- }
- return NoFault;
- case TSDEV_CC_DIR0:
- case TSDEV_CC_DIR1:
- case TSDEV_CC_DIR2:
- case TSDEV_CC_DIR3:
- panic("TSDEV_CC_DIR write not implemented\n");
- case TSDEV_CC_DRIR:
- panic("TSDEV_CC_DRIR write not implemented\n");
- case TSDEV_CC_PRBEN:
- panic("TSDEV_CC_PRBEN write not implemented\n");
- case TSDEV_CC_IIC0:
- case TSDEV_CC_IIC1:
- case TSDEV_CC_IIC2:
- case TSDEV_CC_IIC3:
- panic("TSDEV_CC_IICx write not implemented\n");
- case TSDEV_CC_MPR0:
- case TSDEV_CC_MPR1:
- case TSDEV_CC_MPR2:
- case TSDEV_CC_MPR3:
- panic("TSDEV_CC_MPRx write not implemented\n");
- case TSDEV_CC_IPIR:
- clearIPI(*(uint64_t*)data);
- return NoFault;
- case TSDEV_CC_ITIR:
- clearITI(*(uint64_t*)data);
- return NoFault;
- case TSDEV_CC_IPIQ:
- reqIPI(*(uint64_t*)data);
- return NoFault;
- default:
- panic("default in cchip read reached, accessing 0x%x\n");
- }
+ //If it is the 4-7th bit, clear the RTC interrupt
+ uint64_t itintr;
+ itintr = (pkt.get<uint64_t>() >> 4) & 0xF;
+ if (itintr) {
+ clearITI(itintr);
+ supportedWrite = true;
+ }
- break;
- case sizeof(uint32_t):
- case sizeof(uint16_t):
- case sizeof(uint8_t):
- default:
- panic("invalid access size(?) for tsunami register!\n");
- }
+ // ignore NXMs
+ if (pkt.get<uint64_t>() & 0x10000000)
+ supportedWrite = true;
+
+ if(!supportedWrite)
+ panic("TSDEV_CC_MISC write not implemented\n");
+
+ break;
+ case TSDEV_CC_AAR0:
+ case TSDEV_CC_AAR1:
+ case TSDEV_CC_AAR2:
+ case TSDEV_CC_AAR3:
+ panic("TSDEV_CC_AARx write not implemeted\n");
+ case TSDEV_CC_DIM0:
+ case TSDEV_CC_DIM1:
+ case TSDEV_CC_DIM2:
+ case TSDEV_CC_DIM3:
+ int number;
+ if(regnum == TSDEV_CC_DIM0)
+ number = 0;
+ else if(regnum == TSDEV_CC_DIM1)
+ number = 1;
+ else if(regnum == TSDEV_CC_DIM2)
+ number = 2;
+ else
+ number = 3;
+
+ uint64_t bitvector;
+ uint64_t olddim;
+ uint64_t olddir;
+
+ olddim = dim[number];
+ olddir = dir[number];
+ dim[number] = pkt.get<uint64_t>();
+ dir[number] = dim[number] & drir;
+ for(int x = 0; x < 64; x++)
+ {
+ bitvector = ULL(1) << x;
+ // Figure out which bits have changed
+ if ((dim[number] & bitvector) != (olddim & bitvector))
+ {
+ // The bit is now set and it wasn't before (set)
+ if((dim[number] & bitvector) && (dir[number] & bitvector))
+ {
+ tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
+ }
+ else if ((olddir & bitvector) &&
+ !(dir[number] & bitvector))
+ {
+ // The bit was set and now its now clear and
+ // we were interrupting on that bit before
+ tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
+ DPRINTF(Tsunami, "dim write resulting in clear"
+ " dir interrupt to cpu %d\n",
+ x);
+
+ }
- DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
- return NoFault;
+ }
+ }
+ break;
+ case TSDEV_CC_DIR0:
+ case TSDEV_CC_DIR1:
+ case TSDEV_CC_DIR2:
+ case TSDEV_CC_DIR3:
+ panic("TSDEV_CC_DIR write not implemented\n");
+ case TSDEV_CC_DRIR:
+ panic("TSDEV_CC_DRIR write not implemented\n");
+ case TSDEV_CC_PRBEN:
+ panic("TSDEV_CC_PRBEN write not implemented\n");
+ case TSDEV_CC_IIC0:
+ case TSDEV_CC_IIC1:
+ case TSDEV_CC_IIC2:
+ case TSDEV_CC_IIC3:
+ panic("TSDEV_CC_IICx write not implemented\n");
+ case TSDEV_CC_MPR0:
+ case TSDEV_CC_MPR1:
+ case TSDEV_CC_MPR2:
+ case TSDEV_CC_MPR3:
+ panic("TSDEV_CC_MPRx write not implemented\n");
+ case TSDEV_CC_IPIR:
+ clearIPI(pkt.get<uint64_t>());
+ break;
+ case TSDEV_CC_ITIR:
+ clearITI(pkt.get<uint64_t>());
+ break;
+ case TSDEV_CC_IPIQ:
+ reqIPI(pkt.get<uint64_t>());
+ break;
+ default:
+ panic("default in cchip read reached, accessing 0x%x\n");
+ } // swtich(regnum)
+ } // not BIG_TSUNAMI write
+ pkt.result = Success;
+ return pioDelay;
}
void
@@ -471,11 +447,11 @@ TsunamiCChip::postRTC()
for (int i = 0; i < size; i++) {
uint64_t cpumask = ULL(1) << i;
- if (!(cpumask & itint)) {
- itint |= cpumask;
- tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
- DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
- }
+ if (!(cpumask & itint)) {
+ itint |= cpumask;
+ tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
+ DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
+ }
}
}
@@ -490,11 +466,11 @@ TsunamiCChip::postDRIR(uint32_t interrupt)
for(int i=0; i < size; i++) {
dir[i] = dim[i] & drir;
- if (dim[i] & bitvector) {
- tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
- DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
+ if (dim[i] & bitvector) {
+ tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
"interrupt %d\n",i, interrupt);
- }
+ }
}
}
@@ -509,25 +485,19 @@ TsunamiCChip::clearDRIR(uint32_t interrupt)
{
drir &= ~bitvector;
for(int i=0; i < size; i++) {
- if (dir[i] & bitvector) {
- tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
- DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
+ if (dir[i] & bitvector) {
+ tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
+ DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
"interrupt %d\n",i, interrupt);
- }
- dir[i] = dim[i] & drir;
+ }
+ dir[i] = dim[i] & drir;
}
}
else
DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
}
-Tick
-TsunamiCChip::cacheAccess(MemReqPtr &req)
-{
- return curTick + pioLatency;
-}
-
void
TsunamiCChip::serialize(std::ostream &os)
@@ -551,30 +521,34 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
- SimObjectParam<Tsunami *> tsunami;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> pio_bus;
+ Param<Addr> pio_addr;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+ SimObjectParam<Tsunami *> tsunami;
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
- INIT_PARAM(tsunami, "Tsunami"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(system, "system object"),
+ INIT_PARAM(tsunami, "Tsunami")
END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
CREATE_SIM_OBJECT(TsunamiCChip)
{
- return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier,
- pio_bus, pio_latency);
+ TsunamiCChip::Params *p = new TsunamiCChip::Params;
+ p->name = getInstanceName();
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->platform = platform;
+ p->system = system;
+ p->tsunami = tsunami;
+ return new TsunamiCChip(p);
}
REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
index d88ad375f..6cd6cf13f 100644
--- a/dev/tsunami_cchip.hh
+++ b/dev/tsunami_cchip.hh
@@ -37,21 +37,13 @@
#include "base/range.hh"
#include "dev/io_device.hh"
-class MemoryController;
/**
* Tsunami CChip CSR Emulation. This device includes all the interrupt
* handling code for the chipset.
*/
-class TsunamiCChip : public PioDevice
+class TsunamiCChip : public BasicPioDevice
{
- private:
- /** The base address of this device */
- Addr addr;
-
- /** The size of mappad from the above address */
- static const Addr size = 0xfffffff;
-
protected:
/**
* pointer to the tsunami object.
@@ -85,36 +77,24 @@ class TsunamiCChip : public PioDevice
uint64_t itint;
public:
+ struct Params : public BasicPioDevice::Params
+ {
+ Tsunami *tsunami;
+ };
+ protected:
+ const Params *params() const {return (const Params *)_params; }
+
+ public:
/**
* Initialize the Tsunami CChip by setting all of the
* device register to 0.
- * @param name name of this device.
- * @param t pointer back to the Tsunami object that we belong to.
- * @param a address we are mapped at.
- * @param mmu pointer to the memory controller that sends us events.
- * @param hier object to store parameters universal the device hierarchy
- * @param bus The bus that this device is attached to
+ * @param p params struct
*/
- TsunamiCChip(const std::string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier, Bus *pio_bus,
- Tick pio_latency);
-
- /**
- * Process a read to the CChip.
- * @param req Contains the address to read from.
- * @param data A pointer to write the read data to.
- * @return The fault condition of the access.
- */
- virtual Fault read(MemReqPtr &req, uint8_t *data);
+ TsunamiCChip(Params *p);
+ virtual Tick read(Packet &pkt);
- /**
- * Process a write to the CChip.
- * @param req Contains the address to write to.
- * @param data The data to write.
- * @return The fault condition of the access.
- */
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick write(Packet &pkt);
/**
* post an RTC interrupt to the CPU
@@ -165,12 +145,6 @@ class TsunamiCChip : public PioDevice
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
};
#endif // __TSUNAMI_CCHIP_HH__
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index e66d6653b..0efcc1028 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -37,17 +37,15 @@
#include <vector>
#include "base/trace.hh"
-#include "dev/tsunami_io.hh"
-#include "dev/tsunami.hh"
#include "dev/pitreg.h"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "sim/builder.hh"
+#include "dev/rtcreg.h"
#include "dev/tsunami_cchip.hh"
+#include "dev/tsunami.hh"
+#include "dev/tsunami_io.hh"
#include "dev/tsunamireg.h"
-#include "dev/rtcreg.h"
-#include "mem/functional/memory_control.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
using namespace std;
//Should this be AlphaISA?
@@ -79,38 +77,38 @@ TsunamiIO::RTC::set_time(time_t t)
}
void
-TsunamiIO::RTC::writeAddr(const uint8_t *data)
+TsunamiIO::RTC::writeAddr(const uint8_t data)
{
- if (*data <= RTC_STAT_REGD)
- addr = *data;
+ if (data <= RTC_STAT_REGD)
+ addr = data;
else
panic("RTC addresses over 0xD are not implemented.\n");
}
void
-TsunamiIO::RTC::writeData(const uint8_t *data)
+TsunamiIO::RTC::writeData(const uint8_t data)
{
if (addr < RTC_STAT_REGA)
- clock_data[addr] = *data;
+ clock_data[addr] = data;
else {
switch (addr) {
case RTC_STAT_REGA:
- if (*data != (RTCA_32768HZ | RTCA_1024HZ))
+ if (data != (RTCA_32768HZ | RTCA_1024HZ))
panic("Unimplemented RTC register A value write!\n");
- stat_regA = *data;
+ stat_regA = data;
break;
case RTC_STAT_REGB:
- if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
+ if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
panic("Write to RTC reg B bits that are not implemented!\n");
- if (*data & RTCB_PRDC_IE) {
+ if (data & RTCB_PRDC_IE) {
if (!event.scheduled())
event.scheduleIntr();
} else {
if (event.scheduled())
event.deschedule();
}
- stat_regB = *data;
+ stat_regB = data;
break;
case RTC_STAT_REGC:
case RTC_STAT_REGD:
@@ -206,24 +204,24 @@ TsunamiIO::PITimer::PITimer(const string &name)
}
void
-TsunamiIO::PITimer::writeControl(const uint8_t *data)
+TsunamiIO::PITimer::writeControl(const uint8_t data)
{
int rw;
int sel;
- sel = GET_CTRL_SEL(*data);
+ sel = GET_CTRL_SEL(data);
if (sel == PIT_READ_BACK)
panic("PITimer Read-Back Command is not implemented.\n");
- rw = GET_CTRL_RW(*data);
+ rw = GET_CTRL_RW(data);
if (rw == PIT_RW_LATCH_COMMAND)
counter[sel]->latchCount();
else {
counter[sel]->setRW(rw);
- counter[sel]->setMode(GET_CTRL_MODE(*data));
- counter[sel]->setBCD(GET_CTRL_BCD(*data));
+ counter[sel]->setMode(GET_CTRL_MODE(data));
+ counter[sel]->setBCD(GET_CTRL_BCD(data));
}
}
@@ -295,11 +293,11 @@ TsunamiIO::PITimer::Counter::read(uint8_t *data)
}
void
-TsunamiIO::PITimer::Counter::write(const uint8_t *data)
+TsunamiIO::PITimer::Counter::write(const uint8_t data)
{
switch (write_byte) {
case LSB:
- count = (count & 0xFF00) | *data;
+ count = (count & 0xFF00) | data;
if (event.scheduled())
event.deschedule();
@@ -308,7 +306,7 @@ TsunamiIO::PITimer::Counter::write(const uint8_t *data)
break;
case MSB:
- count = (count & 0x00FF) | (*data << 8);
+ count = (count & 0x00FF) | (data << 8);
period = count;
if (period > 0) {
@@ -416,26 +414,17 @@ TsunamiIO::PITimer::Counter::CounterEvent::description()
return "tsunami 8254 Interval timer";
}
-TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
- Addr a, MemoryController *mmu, HierParams *hier,
- Bus *pio_bus, Tick pio_latency, Tick ci)
- : PioDevice(name, t), addr(a), clockInterval(ci), tsunami(t),
- pitimer(name + "pitimer"), rtc(name + ".rtc", t, ci)
+TsunamiIO::TsunamiIO(Params *p)
+ : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
+ rtc(p->name + ".rtc", p->tsunami, p->frequency)
{
- mmu->add_child(this, RangeSize(addr, size));
-
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &TsunamiIO::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- pioLatency = pio_latency * pio_bus->clockRate;
- }
+ pioSize = 0xff;
// set the back pointer from tsunami to myself
tsunami->io = this;
timerData = 0;
- rtc.set_time(init_time == 0 ? time(NULL) : init_time);
+ rtc.set_time(p->init_time == 0 ? time(NULL) : p->init_time);
picr = 0;
picInterrupting = false;
}
@@ -443,185 +432,156 @@ TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
Tick
TsunamiIO::frequency() const
{
- return Clock::Frequency / clockInterval;
+ return Clock::Frequency / params()->frequency;
}
-Fault
-TsunamiIO::read(MemReqPtr &req, uint8_t *data)
+Tick
+TsunamiIO::read(Packet &pkt)
{
- DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
- req->vaddr, req->size, req->vaddr & 0xfff);
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+
+ pkt.time += pioDelay;
+ Addr daddr = pkt.addr - pioAddr;
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt.addr,
+ pkt.size, daddr);
+ pkt.allocate();
- switch(req->size) {
- case sizeof(uint8_t):
+ if (pkt.size == sizeof(uint8_t)) {
switch(daddr) {
// PIC1 mask read
case TSDEV_PIC1_MASK:
- *(uint8_t*)data = ~mask1;
- return NoFault;
+ pkt.set(~mask1);
+ break;
case TSDEV_PIC2_MASK:
- *(uint8_t*)data = ~mask2;
- return NoFault;
+ pkt.set(~mask2);
+ break;
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 NoFault;
+ pkt.set(picr);
+ break;
case TSDEV_PIC2_ISR:
// PIC2 not implemnted... just return 0
- *(uint8_t*)data = 0x00;
- return NoFault;
+ pkt.set(0x00);
+ break;
case TSDEV_TMR0_DATA:
- pitimer.counter0.read(data);
- return NoFault;
+ pitimer.counter0.read(pkt.getPtr<uint8_t>());
+ break;
case TSDEV_TMR1_DATA:
- pitimer.counter1.read(data);
- return NoFault;
+ pitimer.counter1.read(pkt.getPtr<uint8_t>());
+ break;
case TSDEV_TMR2_DATA:
- pitimer.counter2.read(data);
- return NoFault;
+ pitimer.counter2.read(pkt.getPtr<uint8_t>());
+ break;
case TSDEV_RTC_DATA:
- rtc.readData(data);
- return NoFault;
+ rtc.readData(pkt.getPtr<uint8_t>());
+ break;
case TSDEV_CTRL_PORTB:
if (pitimer.counter2.outputHigh())
- *data = PORTB_SPKR_HIGH;
+ pkt.set(PORTB_SPKR_HIGH);
else
- *data = 0x00;
- return NoFault;
+ pkt.set(0x00);
+ break;
default:
- panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
+ panic("I/O Read - va%#x size %d\n", pkt.addr, pkt.size);
}
- case sizeof(uint16_t):
- case sizeof(uint32_t):
- panic("I/O Read - invalid size - va %#x size %d\n",
- req->vaddr, req->size);
-
- case sizeof(uint64_t):
- switch(daddr) {
- case TSDEV_PIC1_ISR:
- // !!! If this is modified 8bit case needs to be too
- // 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 NoFault;
- default:
- panic("I/O Read - invalid size - va %#x size %d\n",
- req->vaddr, req->size);
- }
-
- default:
- panic("I/O Read - invalid size - va %#x size %d\n",
- req->vaddr, req->size);
+ } else if (pkt.size == sizeof(uint64_t)) {
+ if (daddr == TSDEV_PIC1_ISR)
+ pkt.set<uint64_t>(picr);
+ else
+ panic("I/O Read - invalid addr - va %#x size %d\n",
+ pkt.addr, pkt.size);
+ } else {
+ panic("I/O Read - invalid size - va %#x size %d\n", pkt.addr, pkt.size);
}
- panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
-
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
-Fault
-TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
+Tick
+TsunamiIO::write(Packet &pkt)
{
+ pkt.time += pioDelay;
-#if TRACING_ON
- uint8_t dt = *(uint8_t*)data;
- uint64_t dt64 = dt;
-#endif
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ Addr daddr = pkt.addr - pioAddr;
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
- req->vaddr, req->size, req->vaddr & 0xfff, dt64);
+ pkt.addr, pkt.size, pkt.addr & 0xfff, (uint32_t)pkt.get<uint8_t>());
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ assert(pkt.size == sizeof(uint8_t));
- switch(req->size) {
- case sizeof(uint8_t):
- switch(daddr) {
- case TSDEV_PIC1_MASK:
- mask1 = ~(*(uint8_t*)data);
- if ((picr & mask1) && !picInterrupting) {
- picInterrupting = true;
- tsunami->cchip->postDRIR(55);
- DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
- }
- if ((!(picr & mask1)) && picInterrupting) {
- picInterrupting = false;
- tsunami->cchip->clearDRIR(55);
- DPRINTF(Tsunami, "clearing pic interrupt\n");
- }
- return NoFault;
- case TSDEV_PIC2_MASK:
- mask2 = *(uint8_t*)data;
- //PIC2 Not implemented to interrupt
- 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 NoFault;
- case TSDEV_DMA1_CMND:
- return NoFault;
- case TSDEV_DMA2_CMND:
- return NoFault;
- case TSDEV_DMA1_MMASK:
- return NoFault;
- case TSDEV_DMA2_MMASK:
- return NoFault;
- case TSDEV_PIC2_ACK:
- return NoFault;
- case TSDEV_DMA1_RESET:
- return NoFault;
- case TSDEV_DMA2_RESET:
- return NoFault;
- case TSDEV_DMA1_MODE:
- mode1 = *(uint8_t*)data;
- return NoFault;
- case TSDEV_DMA2_MODE:
- mode2 = *(uint8_t*)data;
- return NoFault;
- case TSDEV_DMA1_MASK:
- case TSDEV_DMA2_MASK:
- return NoFault;
- case TSDEV_TMR0_DATA:
- pitimer.counter0.write(data);
- return NoFault;
- case TSDEV_TMR1_DATA:
- pitimer.counter1.write(data);
- return NoFault;
- case TSDEV_TMR2_DATA:
- pitimer.counter2.write(data);
- return NoFault;
- case TSDEV_TMR_CTRL:
- pitimer.writeControl(data);
- return NoFault;
- case TSDEV_RTC_ADDR:
- rtc.writeAddr(data);
- return NoFault;
- case TSDEV_KBD:
- return NoFault;
- case TSDEV_RTC_DATA:
- rtc.writeData(data);
- return NoFault;
- case TSDEV_CTRL_PORTB:
- // System Control Port B not implemented
- return NoFault;
- default:
- panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data);
+ switch(daddr) {
+ case TSDEV_PIC1_MASK:
+ mask1 = ~(pkt.get<uint8_t>());
+ if ((picr & mask1) && !picInterrupting) {
+ picInterrupting = true;
+ tsunami->cchip->postDRIR(55);
+ DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
+ }
+ if ((!(picr & mask1)) && picInterrupting) {
+ picInterrupting = false;
+ tsunami->cchip->clearDRIR(55);
+ DPRINTF(Tsunami, "clearing pic interrupt\n");
}
- case sizeof(uint16_t):
- case sizeof(uint32_t):
- case sizeof(uint64_t):
+ break;
+ case TSDEV_PIC2_MASK:
+ mask2 = pkt.get<uint8_t>();
+ //PIC2 Not implemented to interrupt
+ break;
+ case TSDEV_PIC1_ACK:
+ // clear the interrupt on the PIC
+ picr &= ~(1 << (pkt.get<uint8_t>() & 0xF));
+ if (!(picr & mask1))
+ tsunami->cchip->clearDRIR(55);
+ break;
+ case TSDEV_DMA1_MODE:
+ mode1 = pkt.get<uint8_t>();
+ break;
+ case TSDEV_DMA2_MODE:
+ mode2 = pkt.get<uint8_t>();
+ break;
+ case TSDEV_TMR0_DATA:
+ pitimer.counter0.write(pkt.get<uint8_t>());
+ break;
+ case TSDEV_TMR1_DATA:
+ pitimer.counter1.write(pkt.get<uint8_t>());
+ break;
+ case TSDEV_TMR2_DATA:
+ pitimer.counter2.write(pkt.get<uint8_t>());
+ break;
+ case TSDEV_TMR_CTRL:
+ pitimer.writeControl(pkt.get<uint8_t>());
+ break;
+ case TSDEV_RTC_ADDR:
+ rtc.writeAddr(pkt.get<uint8_t>());
+ break;
+ case TSDEV_RTC_DATA:
+ rtc.writeData(pkt.get<uint8_t>());
+ break;
+ case TSDEV_KBD:
+ case TSDEV_DMA1_CMND:
+ case TSDEV_DMA2_CMND:
+ case TSDEV_DMA1_MMASK:
+ case TSDEV_DMA2_MMASK:
+ case TSDEV_PIC2_ACK:
+ case TSDEV_DMA1_RESET:
+ case TSDEV_DMA2_RESET:
+ case TSDEV_DMA1_MASK:
+ case TSDEV_DMA2_MASK:
+ case TSDEV_CTRL_PORTB:
+ break;
default:
- panic("I/O Write - invalid size - va %#x size %d\n",
- req->vaddr, req->size);
+ panic("I/O Write - va%#x size %d data %#x\n", pkt.addr, pkt.size, pkt.get<uint8_t>());
}
-
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
void
@@ -646,12 +606,6 @@ TsunamiIO::clearPIC(uint8_t bitvector)
}
}
-Tick
-TsunamiIO::cacheAccess(MemReqPtr &req)
-{
- return curTick + pioLatency;
-}
-
void
TsunamiIO::serialize(ostream &os)
{
@@ -686,34 +640,40 @@ TsunamiIO::unserialize(Checkpoint *cp, const string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
- SimObjectParam<Tsunami *> tsunami;
- Param<time_t> time;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> pio_bus;
+ Param<Addr> pio_addr;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
Param<Tick> frequency;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+ Param<time_t> time;
+ SimObjectParam<Tsunami *> tsunami;
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
- INIT_PARAM(tsunami, "Tsunami"),
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(frequency, "clock interrupt frequency"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(system, "system object"),
INIT_PARAM(time, "System time to use (0 for actual time"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM(pio_bus, "The IO Bus to attach to"),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
- INIT_PARAM(frequency, "clock interrupt frequency")
+ INIT_PARAM(tsunami, "Tsunami")
END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
CREATE_SIM_OBJECT(TsunamiIO)
{
- return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier,
- pio_bus, pio_latency, frequency);
+ TsunamiIO::Params *p = new TsunamiIO::Params;
+ p->frequency = frequency;
+ p->name = getInstanceName();
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->platform = platform;
+ p->system = system;
+ p->init_time = time;
+ p->tsunami = tsunami;
+ return new TsunamiIO(p);
}
REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index b024ecd14..c37f3aa16 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -38,21 +38,13 @@
#include "dev/tsunami.hh"
#include "sim/eventq.hh"
-class MemoryController;
-
/**
* Tsunami I/O device is a catch all for all the south bridge stuff we care
* to implement.
*/
-class TsunamiIO : public PioDevice
+class TsunamiIO : public BasicPioDevice
{
private:
- /** The base address of this device */
- Addr addr;
-
- /** The size of mappad from the above address */
- static const Addr size = 0xff;
-
struct tm tm;
protected:
@@ -120,10 +112,10 @@ class TsunamiIO : public PioDevice
void set_time(time_t t);
/** RTC address port: write address of RTC RAM data to access */
- void writeAddr(const uint8_t *data);
+ void writeAddr(const uint8_t data);
/** RTC write data */
- void writeData(const uint8_t *data);
+ void writeData(const uint8_t data);
/** RTC read data */
void readData(uint8_t *data);
@@ -218,7 +210,7 @@ class TsunamiIO : public PioDevice
void read(uint8_t *data);
/** Write a count byte */
- void write(const uint8_t *data);
+ void write(const uint8_t data);
/** Is the output high? */
bool outputHigh();
@@ -254,7 +246,7 @@ class TsunamiIO : public PioDevice
PITimer(const std::string &name);
/** Write control word */
- void writeControl(const uint8_t* data);
+ void writeControl(const uint8_t data);
/**
* Serialize this object to the given output stream.
@@ -289,8 +281,6 @@ class TsunamiIO : public PioDevice
/** Is the pic interrupting right now or not. */
bool picInterrupting;
- Tick clockInterval;
-
/** A pointer to the Tsunami device which be belong to */
Tsunami *tsunami;
@@ -312,33 +302,24 @@ class TsunamiIO : public PioDevice
*/
Tick frequency() const;
+ struct Params : public BasicPioDevice::Params
+ {
+ Tick frequency;
+ Tsunami *tsunami;
+ time_t init_time;
+ };
+ protected:
+ const Params *params() const { return (const Params*)_params; }
+
+ public:
/**
* Initialize all the data for devices supported by Tsunami I/O.
- * @param name name of this device.
- * @param t pointer back to the Tsunami object that we belong to.
- * @param init_time Time (as in seconds since 1970) to set RTC to.
- * @param a address we are mapped at.
- * @param mmu pointer to the memory controller that sends us events.
+ * @param p pointer to Params struct
*/
- TsunamiIO(const std::string &name, Tsunami *t, time_t init_time,
- Addr a, MemoryController *mmu, HierParams *hier, Bus *pio_bus,
- Tick pio_latency, Tick ci);
+ TsunamiIO(Params *p);
- /**
- * Process a read to one of the devices we are emulating.
- * @param req Contains the address to read from.
- * @param data A pointer to write the read data to.
- * @return The fault condition of the access.
- */
- virtual Fault read(MemReqPtr &req, uint8_t *data);
-
- /**
- * Process a write to one of the devices we emulate.
- * @param req Contains the address to write to.
- * @param data The data to write.
- * @return The fault condition of the access.
- */
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
/**
* Post an PIC interrupt to the CPU via the CChip
@@ -365,7 +346,6 @@ class TsunamiIO : public PioDevice
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
- Tick cacheAccess(MemReqPtr &req);
};
#endif // __DEV_TSUNAMI_IO_HH__
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index 46efc3dfe..1323a0548 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -38,11 +38,7 @@
#include "dev/tsunami_pchip.hh"
#include "dev/tsunamireg.h"
#include "dev/tsunami.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
+#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
@@ -50,12 +46,10 @@ using namespace std;
//Should this be AlphaISA?
using namespace TheISA;
-TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier,
- Bus *pio_bus, Tick pio_latency)
- : PioDevice(name, t), addr(a), tsunami(t)
+TsunamiPChip::TsunamiPChip(Params *p)
+: BasicPioDevice(p)
{
- mmu->add_child(this, RangeSize(addr, size));
+ pioSize = 0xfff;
for (int i = 0; i < 4; i++) {
wsba[i] = 0;
@@ -63,195 +57,175 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
tba[i] = 0;
}
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &TsunamiPChip::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- pioLatency = pio_latency * pio_bus->clockRate;
- }
-
-
// initialize pchip control register
pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
//Set back pointer in tsunami
- tsunami->pchip = this;
+ p->tsunami->pchip = this;
}
-Fault
-TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
+Tick
+TsunamiPChip::read(Packet &pkt)
{
- DPRINTF(Tsunami, "read va=%#x size=%d\n",
- req->vaddr, req->size);
-
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
-
- switch (req->size) {
-
- case sizeof(uint64_t):
- switch(daddr) {
- case TSDEV_PC_WSBA0:
- *(uint64_t*)data = wsba[0];
- return NoFault;
- case TSDEV_PC_WSBA1:
- *(uint64_t*)data = wsba[1];
- return NoFault;
- case TSDEV_PC_WSBA2:
- *(uint64_t*)data = wsba[2];
- return NoFault;
- case TSDEV_PC_WSBA3:
- *(uint64_t*)data = wsba[3];
- return NoFault;
- case TSDEV_PC_WSM0:
- *(uint64_t*)data = wsm[0];
- return NoFault;
- case TSDEV_PC_WSM1:
- *(uint64_t*)data = wsm[1];
- return NoFault;
- case TSDEV_PC_WSM2:
- *(uint64_t*)data = wsm[2];
- return NoFault;
- case TSDEV_PC_WSM3:
- *(uint64_t*)data = wsm[3];
- return NoFault;
- case TSDEV_PC_TBA0:
- *(uint64_t*)data = tba[0];
- return NoFault;
- case TSDEV_PC_TBA1:
- *(uint64_t*)data = tba[1];
- return NoFault;
- case TSDEV_PC_TBA2:
- *(uint64_t*)data = tba[2];
- return NoFault;
- case TSDEV_PC_TBA3:
- *(uint64_t*)data = tba[3];
- return NoFault;
- case TSDEV_PC_PCTL:
- *(uint64_t*)data = pctl;
- 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 NoFault;
- case TSDEV_PC_PERRMASK:
- *(uint64_t*)data = 0x00;
- 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 NoFault;
- case TSDEV_PC_PMONCTL:
- panic("PC_PMONCTL not implemented\n");
- case TSDEV_PC_PMONCNT:
- panic("PC_PMONCTN not implemented\n");
- default:
- panic("Default in PChip Read reached reading 0x%x\n", daddr);
-
- } // uint64_t
-
- break;
- case sizeof(uint32_t):
- case sizeof(uint16_t):
- case sizeof(uint8_t):
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+
+
+ pkt.time += pioDelay;
+ pkt.allocate();
+ Addr daddr = (pkt.addr - pioAddr) >> 6;;
+ assert(pkt.size == sizeof(uint64_t));
+
+
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size);
+
+ switch(daddr) {
+ case TSDEV_PC_WSBA0:
+ pkt.set(wsba[0]);
+ break;
+ case TSDEV_PC_WSBA1:
+ pkt.set(wsba[1]);
+ break;
+ case TSDEV_PC_WSBA2:
+ pkt.set(wsba[2]);
+ break;
+ case TSDEV_PC_WSBA3:
+ pkt.set(wsba[3]);
+ break;
+ case TSDEV_PC_WSM0:
+ pkt.set(wsm[0]);
+ break;
+ case TSDEV_PC_WSM1:
+ pkt.set(wsm[1]);
+ break;
+ case TSDEV_PC_WSM2:
+ pkt.set(wsm[2]);
+ break;
+ case TSDEV_PC_WSM3:
+ pkt.set(wsm[3]);
+ break;
+ case TSDEV_PC_TBA0:
+ pkt.set(tba[0]);
+ break;
+ case TSDEV_PC_TBA1:
+ pkt.set(tba[1]);
+ break;
+ case TSDEV_PC_TBA2:
+ pkt.set(tba[2]);
+ break;
+ case TSDEV_PC_TBA3:
+ pkt.set(tba[3]);
+ break;
+ case TSDEV_PC_PCTL:
+ pkt.set(pctl);
+ break;
+ case TSDEV_PC_PLAT:
+ panic("PC_PLAT not implemented\n");
+ case TSDEV_PC_RES:
+ panic("PC_RES not implemented\n");
+ case TSDEV_PC_PERROR:
+ pkt.set((uint64_t)0x00);
+ break;
+ case TSDEV_PC_PERRMASK:
+ pkt.set((uint64_t)0x00);
+ break;
+ case TSDEV_PC_PERRSET:
+ panic("PC_PERRSET not implemented\n");
+ case TSDEV_PC_TLBIV:
+ panic("PC_TLBIV not implemented\n");
+ case TSDEV_PC_TLBIA:
+ pkt.set((uint64_t)0x00); // shouldn't be readable, but linux
+ break;
+ case TSDEV_PC_PMONCTL:
+ panic("PC_PMONCTL not implemented\n");
+ case TSDEV_PC_PMONCNT:
+ panic("PC_PMONCTN not implemented\n");
default:
- panic("invalid access size(?) for tsunami register!\n\n");
+ panic("Default in PChip Read reached reading 0x%x\n", daddr);
}
- DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
+ pkt.result = Success;
+ return pioDelay;
- return NoFault;
}
-Fault
-TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
+Tick
+TsunamiPChip::write(Packet &pkt)
{
- DPRINTF(Tsunami, "write - va=%#x size=%d \n",
- req->vaddr, req->size);
-
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
-
- switch (req->size) {
-
- case sizeof(uint64_t):
- switch(daddr) {
- case TSDEV_PC_WSBA0:
- wsba[0] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSBA1:
- wsba[1] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSBA2:
- wsba[2] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSBA3:
- wsba[3] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSM0:
- wsm[0] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSM1:
- wsm[1] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSM2:
- wsm[2] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_WSM3:
- wsm[3] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_TBA0:
- tba[0] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_TBA1:
- tba[1] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_TBA2:
- tba[2] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_TBA3:
- tba[3] = *(uint64_t*)data;
- return NoFault;
- case TSDEV_PC_PCTL:
- pctl = *(uint64_t*)data;
- 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 NoFault;
- case TSDEV_PC_PERRMASK:
- panic("PC_PERRMASK not implemented\n");
- case TSDEV_PC_PERRSET:
- panic("PC_PERRSET not implemented\n");
- case TSDEV_PC_TLBIV:
- panic("PC_TLBIV not implemented\n");
- case TSDEV_PC_TLBIA:
- return NoFault; // value ignored, supposted to invalidate SG TLB
- case TSDEV_PC_PMONCTL:
- panic("PC_PMONCTL not implemented\n");
- case TSDEV_PC_PMONCNT:
- panic("PC_PMONCTN not implemented\n");
- default:
- panic("Default in PChip Read reached reading 0x%x\n", daddr);
-
- } // uint64_t
-
- break;
- case sizeof(uint32_t):
- case sizeof(uint16_t):
- case sizeof(uint8_t):
- default:
- panic("invalid access size(?) for tsunami register!\n\n");
- }
-
- DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
-
- return NoFault;
+ pkt.time += pioDelay;
+
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ Addr daddr = (pkt.addr - pioAddr) >> 6;
+
+ assert(pkt.size == sizeof(uint64_t));
+
+ DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size);
+
+ switch(daddr) {
+ case TSDEV_PC_WSBA0:
+ wsba[0] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSBA1:
+ wsba[1] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSBA2:
+ wsba[2] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSBA3:
+ wsba[3] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSM0:
+ wsm[0] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSM1:
+ wsm[1] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSM2:
+ wsm[2] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_WSM3:
+ wsm[3] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_TBA0:
+ tba[0] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_TBA1:
+ tba[1] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_TBA2:
+ tba[2] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_TBA3:
+ tba[3] = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_PCTL:
+ pctl = pkt.get<uint64_t>();
+ break;
+ case TSDEV_PC_PLAT:
+ panic("PC_PLAT not implemented\n");
+ case TSDEV_PC_RES:
+ panic("PC_RES not implemented\n");
+ case TSDEV_PC_PERROR:
+ break;
+ case TSDEV_PC_PERRMASK:
+ panic("PC_PERRMASK not implemented\n");
+ case TSDEV_PC_PERRSET:
+ panic("PC_PERRSET not implemented\n");
+ case TSDEV_PC_TLBIV:
+ panic("PC_TLBIV not implemented\n");
+ case TSDEV_PC_TLBIA:
+ break; // value ignored, supposted to invalidate SG TLB
+ case TSDEV_PC_PMONCTL:
+ panic("PC_PMONCTL not implemented\n");
+ case TSDEV_PC_PMONCNT:
+ panic("PC_PMONCTN not implemented\n");
+ default:
+ panic("Default in PChip write reached reading 0x%x\n", daddr);
+
+ } // uint64_t
+
+ pkt.result = Success;
+ return pioDelay;
}
#define DMA_ADDR_MASK ULL(0x3ffffffff)
@@ -311,10 +285,7 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
- memcpy((void *)&pteEntry,
- tsunami->system->
- physmem->dma_addr(pteAddr, sizeof(uint64_t)),
- sizeof(uint64_t));
+ pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t));
dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
@@ -351,38 +322,37 @@ TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(tba, 4);
}
-Tick
-TsunamiPChip::cacheAccess(MemReqPtr &req)
-{
- return curTick + pioLatency;
-}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
- SimObjectParam<Tsunami *> tsunami;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> pio_bus;
+ Param<Addr> pio_addr;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+ SimObjectParam<Tsunami *> tsunami;
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
- INIT_PARAM(tsunami, "Tsunami"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(system, "system object"),
+ INIT_PARAM(tsunami, "Tsunami")
END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
CREATE_SIM_OBJECT(TsunamiPChip)
{
- return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier,
- pio_bus, pio_latency);
+ TsunamiPChip::Params *p = new TsunamiPChip::Params;
+ p->name = getInstanceName();
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->platform = platform;
+ p->system = system;
+ p->tsunami = tsunami;
+ return new TsunamiPChip(p);
}
REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh
index c1d95431b..2f3e8f078 100644
--- a/dev/tsunami_pchip.hh
+++ b/dev/tsunami_pchip.hh
@@ -37,28 +37,12 @@
#include "base/range.hh"
#include "dev/io_device.hh"
-class MemoryController;
-
/**
* A very simple implementation of the Tsunami PCI interface chips.
*/
-class TsunamiPChip : public PioDevice
+class TsunamiPChip : public BasicPioDevice
{
- private:
- /** The base address of this device */
- Addr addr;
-
- /** The size of mappad from the above address */
- static const Addr size = 0xfff;
-
protected:
- /**
- * pointer to the tsunami object.
- * This is our access to all the other tsunami
- * devices.
- */
- Tsunami *tsunami;
-
/** Pchip control register */
uint64_t pctl;
@@ -72,18 +56,19 @@ class TsunamiPChip : public PioDevice
uint64_t tba[4];
public:
+ struct Params : public BasicPioDevice::Params
+ {
+ Tsunami *tsunami;
+ };
+ protected:
+ const Params *params() const { return (const Params*)_params; }
+
+ public:
/**
* Register the PChip with the mmu and init all wsba, wsm, and tba to 0
- * @param name the name of thes device
- * @param t a pointer to the tsunami device
- * @param a the address which we respond to
- * @param mmu the mmu we are to register with
- * @param hier object to store parameters universal the device hierarchy
- * @param bus The bus that this device is attached to
+ * @param p pointer to the parameters struct
*/
- TsunamiPChip(const std::string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier, Bus *pio_bus,
- Tick pio_latency);
+ TsunamiPChip(Params *p);
/**
* Translate a PCI bus address to a memory address for DMA.
@@ -93,21 +78,8 @@ class TsunamiPChip : public PioDevice
*/
Addr translatePciToDma(Addr busAddr);
- /**
- * Process a read to the PChip.
- * @param req Contains the address to read from.
- * @param data A pointer to write the read data to.
- * @return The fault condition of the access.
- */
- virtual Fault read(MemReqPtr &req, uint8_t *data);
-
- /**
- * Process a write to the PChip.
- * @param req Contains the address to write to.
- * @param data The data to write.
- * @return The fault condition of the access.
- */
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
/**
* Serialize this object to the given output stream.
@@ -121,13 +93,6 @@ class TsunamiPChip : public PioDevice
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
};
#endif // __TSUNAMI_PCHIP_HH__
diff --git a/dev/uart.cc b/dev/uart.cc
index b2eeb8e9f..4a9f2b505 100644
--- a/dev/uart.cc
+++ b/dev/uart.cc
@@ -27,39 +27,19 @@
*/
/** @file
- * Implements a 8250 UART
+ * Implements a base class for UARTs
*/
-#include <string>
-#include <vector>
-
-#include "base/inifile.hh"
-#include "base/str.hh" // for to_number
-#include "base/trace.hh"
#include "dev/simconsole.hh"
#include "dev/uart.hh"
#include "dev/platform.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
#include "sim/builder.hh"
using namespace std;
-Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
- Addr s, HierParams *hier, Bus *bus, Tick pio_latency, Platform *p)
- : PioDevice(name, p), addr(a), size(s), cons(c)
+Uart::Uart(Params *p)
+ : BasicPioDevice(p), platform(p->platform), cons(p->cons)
{
- mmu->add_child(this, RangeSize(addr, size));
-
-
- if (bus) {
- pioInterface = newPioInterface(name, hier, bus, this,
- &Uart::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- pioLatency = pio_latency * bus->clockRate;
- }
status = 0;
@@ -68,11 +48,5 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
platform->uart = this;
}
-Tick
-Uart::cacheAccess(MemReqPtr &req)
-{
- return curTick + pioLatency;
-}
-
DEFINE_SIM_OBJECT_CLASS_NAME("Uart", Uart)
diff --git a/dev/uart.hh b/dev/uart.hh
index 78b1dc68e..2dd15d9b8 100644
--- a/dev/uart.hh
+++ b/dev/uart.hh
@@ -37,30 +37,27 @@
#include "dev/io_device.hh"
class SimConsole;
-class MemoryController;
class Platform;
const int RX_INT = 0x1;
const int TX_INT = 0x2;
-class Uart : public PioDevice
+class Uart : public BasicPioDevice
{
protected:
int status;
- Addr addr;
- Addr size;
+ Platform *platform;
SimConsole *cons;
public:
- Uart(const std::string &name, SimConsole *c, MemoryController *mmu,
- Addr a, Addr s, HierParams *hier, Bus *bus, Tick pio_latency,
- Platform *p);
-
- virtual Fault read(MemReqPtr &req, uint8_t *data) = 0;
- virtual Fault write(MemReqPtr &req, const uint8_t *data) = 0;
+ struct Params : public BasicPioDevice::Params
+ {
+ SimConsole *cons;
+ };
+ Uart(Params *p);
/**
* Inform the uart that there is data available.
@@ -74,12 +71,9 @@ class Uart : public PioDevice
*/
bool intStatus() { return status ? true : false; }
- /**
- * Return how long this access will take.
- * @param req the memory request to calcuate
- * @return Tick when the request is done
- */
- Tick cacheAccess(MemReqPtr &req);
+ protected:
+ const Params *params() const {return (const Params *)_params; }
+
};
#endif // __UART_HH__
diff --git a/dev/uart8250.cc b/dev/uart8250.cc
index 65bccee86..15752c735 100644
--- a/dev/uart8250.cc
+++ b/dev/uart8250.cc
@@ -33,16 +33,13 @@
#include <string>
#include <vector>
+#include "arch/alpha/ev5.hh"
#include "base/inifile.hh"
#include "base/str.hh" // for to_number
#include "base/trace.hh"
#include "dev/simconsole.hh"
#include "dev/uart8250.hh"
#include "dev/platform.hh"
-#include "mem/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#include "mem/bus/pio_interface_impl.hh"
-#include "mem/functional/memory_control.hh"
#include "sim/builder.hh"
using namespace std;
@@ -99,34 +96,37 @@ Uart8250::IntrEvent::scheduleIntr()
}
-Uart8250::Uart8250(const string &name, SimConsole *c, MemoryController *mmu,
- Addr a, Addr s, HierParams *hier, Bus *pio_bus,
- Tick pio_latency, Platform *p)
- : Uart(name, c, mmu, a, s, hier, pio_bus, pio_latency, p),
- txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
+Uart8250::Uart8250(Params *p)
+ : Uart(p), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
{
+ pioSize = 8;
+
IER = 0;
DLAB = 0;
LCR = 0;
MCR = 0;
-
}
-Fault
-Uart8250::read(MemReqPtr &req, uint8_t *data)
+Tick
+Uart8250::read(Packet &pkt)
{
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
- DPRINTF(Uart, " read register %#x\n", daddr);
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ assert(pkt.size == 1);
- assert(req->size == 1);
+ pkt.time += pioDelay;
+ Addr daddr = pkt.addr - pioAddr;
+ pkt.allocate();
+
+ DPRINTF(Uart, " read register %#x\n", daddr);
switch (daddr) {
case 0x0:
if (!(LCR & 0x80)) { // read byte
if (cons->dataAvailable())
- cons->in(*data);
+ cons->in(*pkt.getPtr<uint8_t>());
else {
- *(uint8_t*)data = 0;
+ pkt.set((uint8_t)0);
// A limited amount of these are ok.
DPRINTF(Uart, "empty read of RX register\n");
}
@@ -141,7 +141,7 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
break;
case 0x1:
if (!(LCR & 0x80)) { // Intr Enable Register(IER)
- *(uint8_t*)data = IER;
+ pkt.set(IER);
} else { // DLM divisor latch MSB
;
}
@@ -150,17 +150,17 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
if (status & RX_INT) /* Rx data interrupt has a higher priority */
- *(uint8_t*)data = IIR_RXID;
+ pkt.set(IIR_RXID);
else if (status & TX_INT)
- *(uint8_t*)data = IIR_TXID;
+ pkt.set(IIR_TXID);
else
- *(uint8_t*)data = IIR_NOPEND;
+ pkt.set(IIR_NOPEND);
//Tx interrupts are cleared on IIR reads
status &= ~TX_INT;
break;
case 0x3: // Line Control Register (LCR)
- *(uint8_t*)data = LCR;
+ pkt.set(LCR);
break;
case 0x4: // Modem Control Register (MCR)
break;
@@ -171,34 +171,42 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
if (cons->dataAvailable())
lsr = UART_LSR_DR;
lsr |= UART_LSR_TEMT | UART_LSR_THRE;
- *(uint8_t*)data = lsr;
+ pkt.set(lsr);
break;
case 0x6: // Modem Status Register (MSR)
- *(uint8_t*)data = 0;
+ pkt.set((uint8_t)0);
break;
case 0x7: // Scratch Register (SCR)
- *(uint8_t*)data = 0; // doesn't exist with at 8250.
+ pkt.set((uint8_t)0); // doesn't exist with at 8250.
break;
default:
panic("Tried to access a UART port that doesn't exist\n");
break;
}
-
- return NoFault;
-
+/* uint32_t d32 = *data;
+ DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32);
+*/
+ pkt.result = Success;
+ return pioDelay;
}
-Fault
-Uart8250::write(MemReqPtr &req, const uint8_t *data)
+Tick
+Uart8250::write(Packet &pkt)
{
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
- DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
+ assert(pkt.result == Unknown);
+ assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
+ assert(pkt.size == 1);
+
+ pkt.time += pioDelay;
+ Addr daddr = pkt.addr - pioAddr;
+
+ DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt.get<uint8_t>());
switch (daddr) {
case 0x0:
if (!(LCR & 0x80)) { // write byte
- cons->out(*(uint8_t *)data);
+ cons->out(pkt.get<uint8_t>());
platform->clearConsoleInt();
status &= ~TX_INT;
if (UART_IER_THRI & IER)
@@ -209,7 +217,7 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data)
break;
case 0x1:
if (!(LCR & 0x80)) { // Intr Enable Register(IER)
- IER = *(uint8_t*)data;
+ IER = pkt.get<uint8_t>();
if (UART_IER_THRI & IER)
{
DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
@@ -243,10 +251,10 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data)
case 0x2: // FIFO Control Register (FCR)
break;
case 0x3: // Line Control Register (LCR)
- LCR = *(uint8_t*)data;
+ LCR = pkt.get<uint8_t>();
break;
case 0x4: // Modem Control Register (MCR)
- if (*(uint8_t*)data == (UART_MCR_LOOP | 0x0A))
+ if (pkt.get<uint8_t>() == (UART_MCR_LOOP | 0x0A))
MCR = 0x9A;
break;
case 0x7: // Scratch Register (SCR)
@@ -256,7 +264,8 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data)
panic("Tried to access a UART port that doesn't exist\n");
break;
}
- return NoFault;
+ pkt.result = Success;
+ return pioDelay;
}
void
@@ -271,6 +280,14 @@ Uart8250::dataAvailable()
}
+void
+Uart8250::addressRanges(AddrRangeList &range_list)
+{
+ assert(pioSize != 0);
+ range_list.clear();
+ range_list.push_back(RangeSize(pioAddr, pioSize));
+}
+
void
@@ -315,35 +332,35 @@ Uart8250::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart8250)
- SimObjectParam<SimConsole *> console;
- SimObjectParam<MemoryController *> mmu;
- SimObjectParam<Platform *> platform;
- Param<Addr> addr;
- Param<Addr> size;
- SimObjectParam<Bus*> pio_bus;
+ Param<Addr> pio_addr;
Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
-
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<SimConsole *> sim_console;
+ SimObjectParam<System *> system;
END_DECLARE_SIM_OBJECT_PARAMS(Uart8250)
BEGIN_INIT_SIM_OBJECT_PARAMS(Uart8250)
- INIT_PARAM(console, "The console"),
- INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(platform, "Pointer to platfrom"),
- INIT_PARAM(addr, "Device Address"),
- INIT_PARAM_DFLT(size, "Device size", 0x8),
- INIT_PARAM(pio_bus, ""),
- INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(sim_console, "The Simulator Console"),
+ INIT_PARAM(system, "system object")
END_INIT_SIM_OBJECT_PARAMS(Uart8250)
CREATE_SIM_OBJECT(Uart8250)
{
- return new Uart8250(getInstanceName(), console, mmu, addr, size, hier,
- pio_bus, pio_latency, platform);
+ Uart8250::Params *p = new Uart8250::Params;
+ p->name = getInstanceName();
+ p->pio_addr = pio_addr;
+ p->pio_delay = pio_latency;
+ p->platform = platform;
+ p->cons = sim_console;
+ p->system = system;
+ return new Uart8250(p);
}
REGISTER_SIM_OBJECT("Uart8250", Uart8250)
+
diff --git a/dev/uart8250.hh b/dev/uart8250.hh
index 63d1da3cf..19e4438bc 100644
--- a/dev/uart8250.hh
+++ b/dev/uart8250.hh
@@ -30,8 +30,8 @@
* Defines a 8250 UART
*/
-#ifndef __TSUNAMI_UART_HH__
-#define __TSUNAMI_UART_HH__
+#ifndef __DEV_UART8250_HH__
+#define __DEV_UART8250_HH__
#include "dev/tsunamireg.h"
#include "base/range.hh"
@@ -44,16 +44,15 @@
* bit 2:1 ID of highest priority interrupt
* bit 7:3 zeroes
*/
-#define IIR_NOPEND 0x1
+const uint8_t IIR_NOPEND = 0x1;
// Interrupt IDs
-#define IIR_MODEM 0x00 /* Modem Status (lowest priority) */
-#define IIR_TXID 0x02 /* Tx Data */
-#define IIR_RXID 0x04 /* Rx Data */
-#define IIR_LINE 0x06 /* Rx Line Status (highest priority)*/
+const uint8_t IIR_MODEM = 0x00; /* Modem Status (lowest priority) */
+const uint8_t IIR_TXID = 0x02; /* Tx Data */
+const uint8_t IIR_RXID = 0x04; /* Rx Data */
+const uint8_t IIR_LINE = 0x06; /* Rx Line Status (highest priority)*/
class SimConsole;
-class MemoryController;
class Platform;
class Uart8250 : public Uart
@@ -79,12 +78,11 @@ class Uart8250 : public Uart
IntrEvent rxIntrEvent;
public:
- Uart8250(const std::string &name, SimConsole *c, MemoryController *mmu,
- Addr a, Addr s, HierParams *hier, Bus *pio_bus, Tick pio_latency,
- Platform *p);
+ Uart8250(Params *p);
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ virtual Tick read(Packet &pkt);
+ virtual Tick write(Packet &pkt);
+ virtual void addressRanges(AddrRangeList &range_list);
/**
diff --git a/kern/linux/events.cc b/kern/linux/events.cc
index 9f50eef04..b688e9dd0 100644
--- a/kern/linux/events.cc
+++ b/kern/linux/events.cc
@@ -46,7 +46,7 @@ DebugPrintkEvent::process(ExecContext *xc)
DPRINTFN("");
}
- AlphaArguments args(xc);
+ AlphaISA::AlphaArguments args(xc);
Printk(args);
SkipFuncEvent::process(xc);
}
diff --git a/kern/linux/linux.hh b/kern/linux/linux.hh
index 0dbccf546..63e0dd5ca 100644
--- a/kern/linux/linux.hh
+++ b/kern/linux/linux.hh
@@ -44,8 +44,11 @@ class Linux {};
#include <sys/types.h>
#include <unistd.h>
+#include "arch/isa_traits.hh"
#include "sim/syscall_emul.hh"
+class TranslatingPort;
+
///
/// This class encapsulates the types, structures, constants,
/// functions, and syscall-number mappings specific to the Alpha Linux
@@ -72,33 +75,6 @@ class Linux {
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 {
@@ -156,46 +132,12 @@ class Linux {
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
@@ -208,12 +150,6 @@ class Linux {
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 {
@@ -240,8 +176,10 @@ class Linux {
/// memory space. Used by stat(), fstat(), and lstat().
#if !BSD_HOST
static void
- copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat *host)
{
+ using namespace TheISA;
+
TypedBufferArg<Linux::tgt_stat> tgt(addr);
tgt->st_dev = htog(host->st_dev);
@@ -264,8 +202,10 @@ class Linux {
// 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)
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat64 *host)
{
+ using namespace TheISA;
+
TypedBufferArg<Linux::tgt_stat> tgt(addr);
tgt->st_dev = htog(host->st_dev);
@@ -289,8 +229,10 @@ class Linux {
// Same for stat64
static void
- copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host)
+ copyOutStat64Buf(TranslatingPort *mem, int fd, Addr addr, hst_stat64 *host)
{
+ using namespace TheISA;
+
TypedBufferArg<Linux::tgt_stat64> tgt(addr);
// fd == 1 checks are because libc does some checks
diff --git a/kern/linux/printk.cc b/kern/linux/printk.cc
index f5313759b..918b8dabe 100644
--- a/kern/linux/printk.cc
+++ b/kern/linux/printk.cc
@@ -36,7 +36,7 @@ using namespace std;
void
-Printk(AlphaArguments args)
+Printk(AlphaISA::AlphaArguments args)
{
char *p = (char *)args++;
diff --git a/kern/linux/printk.hh b/kern/linux/printk.hh
index 45eab6b88..b88c40f5e 100644
--- a/kern/linux/printk.hh
+++ b/kern/linux/printk.hh
@@ -29,8 +29,8 @@
#ifndef __PRINTK_HH__
#define __PRINTK_HH__
-class AlphaArguments;
+class AlphaISA::AlphaArguments;
-void Printk(AlphaArguments args);
+void Printk(AlphaISA::AlphaArguments args);
#endif // __PRINTK_HH__
diff --git a/kern/system_events.cc b/kern/system_events.cc
index 9b9861497..fd5c12e44 100644
--- a/kern/system_events.cc
+++ b/kern/system_events.cc
@@ -26,8 +26,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "encumbered/cpu/full/cpu.hh"
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "kern/kernel_stats.hh"
+#include "kern/system_events.hh"
+#include "sim/system.hh"
using namespace TheISA;
@@ -41,11 +44,12 @@ SkipFuncEvent::process(ExecContext *xc)
xc->setPC(newpc);
xc->setNextPC(xc->readPC() + sizeof(TheISA::MachInst));
-
+/*
BranchPred *bp = xc->getCpuPtr()->getBranchPred();
if (bp != NULL) {
bp->popRAS(xc->getThreadNum());
}
+*/
}
diff --git a/kern/tru64/dump_mbuf.hh b/kern/tru64/dump_mbuf.hh
index 0ff5da3d7..9e1698ff1 100644
--- a/kern/tru64/dump_mbuf.hh
+++ b/kern/tru64/dump_mbuf.hh
@@ -29,10 +29,10 @@
#ifndef __DUMP_MBUF_HH__
#define __DUMP_MBUF_HH__
-class AlphaArguments;
+#include "arch/arguments.hh"
namespace tru64 {
- void DumpMbuf(AlphaArguments args);
+ void DumpMbuf(AlphaISA::AlphaArguments args);
}
#endif // __DUMP_MBUF_HH__
diff --git a/kern/tru64/printf.cc b/kern/tru64/printf.cc
index 77ac17c3a..319d36673 100644
--- a/kern/tru64/printf.cc
+++ b/kern/tru64/printf.cc
@@ -40,7 +40,7 @@ using namespace std;
namespace tru64 {
void
-Printf(AlphaArguments args)
+Printf(AlphaISA::AlphaArguments args)
{
char *p = (char *)args++;
diff --git a/kern/tru64/printf.hh b/kern/tru64/printf.hh
index a48b4482c..61236e83a 100644
--- a/kern/tru64/printf.hh
+++ b/kern/tru64/printf.hh
@@ -29,10 +29,10 @@
#ifndef __PRINTF_HH__
#define __PRINTF_HH__
-class AlphaArguments;
+#include "arch/arguments.hh"
namespace tru64 {
- void Printf(AlphaArguments args);
+ void Printf(AlphaISA::AlphaArguments args);
}
#endif // __PRINTF_HH__
diff --git a/kern/tru64/tru64.hh b/kern/tru64/tru64.hh
index 112f00f31..91db5bb84 100644
--- a/kern/tru64/tru64.hh
+++ b/kern/tru64/tru64.hh
@@ -55,12 +55,12 @@ class Tru64 {};
#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;
+class TranslatingPort;
+
///
/// This class encapsulates the types, structures, constants,
/// functions, and syscall-number mappings specific to the Alpha Tru64
@@ -85,32 +85,6 @@ class Tru64 {
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
@@ -246,33 +220,6 @@ class Tru64 {
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
@@ -280,21 +227,6 @@ class Tru64 {
};
- /// 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
@@ -309,24 +241,12 @@ class Tru64 {
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
@@ -372,8 +292,6 @@ class Tru64 {
};
- /// For table().
- static const int TBL_SYSINFO = 12;
/// For table().
struct tbl_sysinfo {
@@ -540,8 +458,10 @@ class Tru64 {
/// memory space. Used by stat(), fstat(), and lstat().
template <class T>
static void
- copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host)
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host)
{
+ using namespace TheISA;
+
TypedBufferArg<T> tgt(addr);
tgt->st_dev = htog(host->st_dev);
@@ -566,8 +486,10 @@ class Tru64 {
/// memory space. Used by statfs() and fstatfs().
template <class T>
static void
- copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host)
+ copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host)
{
+ using namespace TheISA;
+
TypedBufferArg<T> tgt(addr);
#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
@@ -590,13 +512,13 @@ class Tru64 {
class F64 {
public:
- static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
+ static void copyOutStatBuf(TranslatingPort *mem, Addr addr,
global_stat *host)
{
Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host);
}
- static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
+ static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr,
global_statfs *host)
{
Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host);
@@ -605,13 +527,13 @@ class Tru64 {
class PreF64 {
public:
- static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
+ static void copyOutStatBuf(TranslatingPort *mem, Addr addr,
global_stat *host)
{
Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host);
}
- static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
+ static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr,
global_statfs *host)
{
Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host);
@@ -623,8 +545,10 @@ class Tru64 {
/// 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)
+ copyOutPreF64StatBuf(TranslatingPort *mem, Addr addr, struct stat *host)
{
+ using namespace TheISA;
+
TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
tgt->st_dev = htog(host->st_dev);
@@ -654,6 +578,8 @@ class Tru64 {
getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace TheISA;
+
#ifdef __CYGWIN__
panic("getdirent not implemented on cygwin!");
#else
@@ -666,7 +592,7 @@ class Tru64 {
// just pass basep through uninterpreted.
TypedBufferArg<int64_t> basep(tgt_basep);
- basep.copyIn(xc->getMemPtr());
+ basep.copyIn(xc->getMemPort());
long host_basep = (off_t)htog((int64_t)*basep);
int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
@@ -693,7 +619,7 @@ class Tru64 {
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_dp.copyOut(xc->getMemPort());
tgt_buf_ptr += tgt_bufsize;
host_buf_ptr += host_dp->d_reclen;
@@ -702,7 +628,7 @@ class Tru64 {
delete [] host_buf;
*basep = htog((int64_t)host_basep);
- basep.copyOut(xc->getMemPtr());
+ basep.copyOut(xc->getMemPort());
return tgt_buf_ptr - tgt_buf;
#endif
@@ -713,10 +639,12 @@ class Tru64 {
sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace TheISA;
+
using TheISA::RegFile;
TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
- sc.copyIn(xc->getMemPtr());
+ sc.copyIn(xc->getMemPort());
// Restore state from sigcontext structure.
// Note that we'll advance PC <- NPC before the end of the cycle,
@@ -726,7 +654,7 @@ class Tru64 {
for (int i = 0; i < 31; ++i) {
xc->setIntReg(i, htog(sc->sc_regs[i]));
- xc->setFloatRegInt(i, htog(sc->sc_fpregs[i]));
+ xc->setFloatRegBits(i, htog(sc->sc_fpregs[i]));
}
xc->setMiscReg(TheISA::Fpcr_DepTag, htog(sc->sc_fpcr));
@@ -734,42 +662,6 @@ class Tru64 {
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
@@ -780,9 +672,11 @@ class Tru64 {
stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace TheISA;
+
TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
- argp.copyIn(xc->getMemPtr());
+ argp.copyIn(xc->getMemPort());
// if the user chose an address, just let them have it. Otherwise
// pick one for them.
@@ -791,7 +685,7 @@ class Tru64 {
int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
htog(argp->gsize));
process->next_thread_stack_base -= stack_size;
- argp.copyOut(xc->getMemPtr());
+ argp.copyOut(xc->getMemPort());
}
return 0;
@@ -808,10 +702,13 @@ class Tru64 {
nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace std;
+ using namespace TheISA;
+
TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
- attrp.copyIn(xc->getMemPtr());
+ attrp.copyIn(xc->getMemPort());
if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
cerr << "nxm_task_init: thread library version mismatch! "
@@ -852,7 +749,7 @@ class Tru64 {
config->nxm_slot_state = htog(slot_state_addr);
config->nxm_rad[0] = htog(rad_state_addr);
- config.copyOut(xc->getMemPtr());
+ config.copyOut(xc->getMemPort());
// initialize the slot_state array and copy it out
TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
@@ -865,7 +762,7 @@ class Tru64 {
(i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
}
- slot_state.copyOut(xc->getMemPtr());
+ slot_state.copyOut(xc->getMemPort());
// same for the per-RAD "shared" struct. Note that we need to
// allocate extra bytes for the per-VP array which is embedded at
@@ -899,13 +796,13 @@ class Tru64 {
}
}
- rad_state.copyOut(xc->getMemPtr());
+ rad_state.copyOut(xc->getMemPort());
//
// copy pointer to shared config area out to user
//
*configptr_ptr = htog(config_addr);
- configptr_ptr.copyOut(xc->getMemPtr());
+ configptr_ptr.copyOut(xc->getMemPort());
// Register this as a valid address range with the process
process->nxm_start = base_addr;
@@ -919,6 +816,8 @@ class Tru64 {
init_exec_context(ExecContext *ec,
Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
{
+ using namespace TheISA;
+
ec->clearArchRegs();
ec->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0));
@@ -937,12 +836,15 @@ class Tru64 {
nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace std;
+ using namespace TheISA;
+
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());
+ attrp.copyIn(xc->getMemPort());
if (gtoh(attrp->version) != NXM_LIB_VERSION) {
cerr << "nxm_thread_create: thread library version mismatch! "
@@ -967,7 +869,7 @@ class Tru64 {
TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
rad_state_size);
- rad_state.copyIn(xc->getMemPtr());
+ rad_state.copyIn(xc->getMemPort());
uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
@@ -978,7 +880,7 @@ class Tru64 {
// This is supposed to be a port number. Make something up.
*kidp = htog(99);
- kidp.copyOut(xc->getMemPtr());
+ kidp.copyOut(xc->getMemPort());
return 0;
} else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
@@ -992,7 +894,7 @@ class Tru64 {
ssp->nxm_u.pth_id = attrp->pthid;
ssp->nxm_u.nxm_active = htog(uniq_val | 1);
- rad_state.copyOut(xc->getMemPtr());
+ rad_state.copyOut(xc->getMemPort());
Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
int slot_state_size =
@@ -1002,7 +904,7 @@ class Tru64 {
slot_state(slot_state_addr,
slot_state_size);
- slot_state.copyIn(xc->getMemPtr());
+ slot_state.copyIn(xc->getMemPort());
if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
cerr << "nxm_thread_createFunc: requested VP slot "
@@ -1014,7 +916,7 @@ class Tru64 {
// doesn't work anyway
slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
- slot_state.copyOut(xc->getMemPtr());
+ slot_state.copyOut(xc->getMemPort());
// Find a free simulator execution context.
for (int i = 0; i < process->numCpus(); ++i) {
@@ -1028,7 +930,7 @@ class Tru64 {
// and get away with just sticking the thread index
// here.
*kidp = htog(thread_index);
- kidp.copyOut(xc->getMemPtr());
+ kidp.copyOut(xc->getMemPort());
return 0;
}
@@ -1059,6 +961,8 @@ class Tru64 {
nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace std;
+
uint64_t tid = xc->getSyscallArg(0);
uint64_t secs = xc->getSyscallArg(1);
uint64_t flags = xc->getSyscallArg(2);
@@ -1076,6 +980,8 @@ class Tru64 {
nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace std;
+
Addr uaddr = xc->getSyscallArg(0);
uint64_t val = xc->getSyscallArg(1);
uint64_t secs = xc->getSyscallArg(2);
@@ -1097,6 +1003,8 @@ class Tru64 {
nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace std;
+
Addr uaddr = xc->getSyscallArg(0);
cout << xc->getCpuPtr()->name() << ": nxm_unblock "
@@ -1127,6 +1035,8 @@ class Tru64 {
activate_waiting_context(Addr uaddr, Process *process,
bool activate_all = false)
{
+ using namespace std;
+
int num_activated = 0;
list<Process::WaitRec>::iterator i = process->waitList.begin();
@@ -1155,14 +1065,16 @@ class Tru64 {
static void
m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
{
+ using namespace TheISA;
+
TypedBufferArg<uint64_t> lockp(uaddr);
- lockp.copyIn(xc->getMemPtr());
+ lockp.copyIn(xc->getMemPort());
if (gtoh(*lockp) == 0) {
// lock is free: grab it
*lockp = htog(1);
- lockp.copyOut(xc->getMemPtr());
+ lockp.copyOut(xc->getMemPort());
} else {
// lock is busy: disable until free
process->waitList.push_back(Process::WaitRec(uaddr, xc));
@@ -1176,7 +1088,7 @@ class Tru64 {
{
TypedBufferArg<uint64_t> lockp(uaddr);
- lockp.copyIn(xc->getMemPtr());
+ lockp.copyIn(xc->getMemPort());
assert(*lockp != 0);
// Check for a process waiting on the lock.
@@ -1185,7 +1097,7 @@ class Tru64 {
// clear lock field if no waiting context is taking over the lock
if (num_waiting == 0) {
*lockp = 0;
- lockp.copyOut(xc->getMemPtr());
+ lockp.copyOut(xc->getMemPort());
}
}
@@ -1209,15 +1121,17 @@ class Tru64 {
m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace TheISA;
+
Addr uaddr = xc->getSyscallArg(0);
TypedBufferArg<uint64_t> lockp(uaddr);
- lockp.copyIn(xc->getMemPtr());
+ lockp.copyIn(xc->getMemPort());
if (gtoh(*lockp) == 0) {
// lock is free: grab it
*lockp = htog(1);
- lockp.copyOut(xc->getMemPtr());
+ lockp.copyOut(xc->getMemPort());
return 0;
} else {
return 1;
@@ -1266,13 +1180,15 @@ class Tru64 {
m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
+ using namespace TheISA;
+
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());
+ lockp.copyIn(xc->getMemPort());
assert(gtoh(*lockp) != 0);
m5_unlock_mutex(lock_addr, process, xc);
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index 8f2be6d9b..69fc5c55d 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -32,7 +32,7 @@
#include "kern/tru64/tru64_events.hh"
#include "kern/tru64/dump_mbuf.hh"
#include "kern/tru64/printf.hh"
-#include "mem/functional/memory_control.hh"
+#include "arch/alpha/ev5.hh"
#include "arch/arguments.hh"
#include "arch/isa_traits.hh"
#include "sim/system.hh"
@@ -50,9 +50,19 @@ BadAddrEvent::process(ExecContext *xc)
uint64_t a0 = xc->readIntReg(ArgumentReg0);
- if (!TheISA::IsK0Seg(a0) ||
- xc->getSystemPtr()->memctrl->badaddr(
- TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
+ AddrRangeList resp;
+ AddrRangeList snoop;
+ AddrRangeIter iter;
+ bool found = false;
+
+ xc->getPhysPort()->getPeerAddressRanges(resp, snoop);
+ for(iter = resp.begin(); iter != resp.end(); iter++)
+ {
+ if (*iter == (TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask))
+ found = true;
+ }
+
+ if (!TheISA::IsK0Seg(a0) || found ) {
DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0);
xc->setIntReg(ReturnValueReg, 0x1);
diff --git a/mem/bridge.cc b/mem/bridge.cc
new file mode 100644
index 000000000..d358ef77b
--- /dev/null
+++ b/mem/bridge.cc
@@ -0,0 +1,263 @@
+
+/*
+ * 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.
+ */
+
+/**
+ * @file Definition of a simple bus bridge without buffering.
+ */
+
+
+#include "base/trace.hh"
+#include "mem/bridge.hh"
+#include "sim/builder.hh"
+
+void
+Bridge::init()
+{
+ // Make sure that both sides are connected to.
+ if (sideA == NULL || sideB == NULL)
+ panic("Both ports of bus bridge are not connected to a bus.\n");
+}
+
+
+/** Function called by the port when the bus is recieving a Timing
+ * transaction.*/
+bool
+Bridge::recvTiming(Packet &pkt, Side id)
+{
+ if (blockedA && id == SideA)
+ return false;
+ if (blockedB && id == SideB)
+ return false;
+
+ if (delay) {
+ if (!sendEvent.scheduled())
+ sendEvent.schedule(curTick + delay);
+ if (id == SideA) {
+ inboundA.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick));
+ blockCheck(SideA);
+ } else {
+ inboundB.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick));
+ blockCheck(SideB);
+ }
+ } else {
+ if (id == SideB) {
+ sideA->sendPkt(pkt);
+ blockCheck(SideB);
+ } else {
+ sideB->sendPkt(pkt);
+ blockCheck(SideA);
+ }
+ }
+ return true;
+
+}
+
+void
+Bridge::blockCheck(Side id)
+{
+ /* Check that we still have buffer space available. */
+ if (id == SideB) {
+ if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) {
+ sideB->sendStatusChange(Port::Blocked);
+ blockedB = true;
+ } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) {
+ sideB->sendStatusChange(Port::Unblocked);
+ blockedB = false;
+ }
+ } else {
+ if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) {
+ sideA->sendStatusChange(Port::Blocked);
+ blockedA = true;
+ } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) {
+ sideA->sendStatusChange(Port::Unblocked);
+ blockedA = false;
+ }
+ }
+}
+
+void Bridge::timerEvent()
+{
+ Tick t = 0;
+
+ assert(inboundA.size() || inboundB.size());
+ if (inboundA.size()) {
+ while (inboundA.front().second <= curTick + delay){
+ sideB->sendPkt(inboundA.front());
+ inboundA.pop_front();
+ }
+ if (inboundA.size())
+ t = inboundA.front().second + delay;
+ }
+ if (inboundB.size()) {
+ while (inboundB.front().second <= curTick + delay){
+ sideB->sendPkt(inboundA.front());
+ inboundB.pop_front();
+ }
+ if (inboundB.size())
+ if (t == 0)
+ t = inboundB.front().second + delay;
+ else
+ t = std::min(t,inboundB.front().second + delay);
+ } else {
+ panic("timerEvent() called but nothing to do?");
+ }
+
+ if (t != 0)
+ sendEvent.schedule(t);
+}
+
+
+void
+Bridge::BridgePort::sendPkt(Packet &pkt)
+{
+ if (!sendTiming(pkt))
+ outbound.push_back(std::make_pair<Packet*,Tick>(&pkt, curTick));
+}
+
+void
+Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p)
+{
+ if (!sendTiming(*p.first))
+ outbound.push_back(p);
+}
+
+
+Packet *
+Bridge::BridgePort::recvRetry()
+{
+ Packet *pkt;
+ assert(outbound.size() > 0);
+ assert(outbound.front().second >= curTick + bridge->delay);
+ pkt = outbound.front().first;
+ outbound.pop_front();
+ bridge->blockCheck(side);
+ return pkt;
+}
+
+/** Function called by the port when the bus is recieving a Atomic
+ * transaction.*/
+Tick
+Bridge::recvAtomic(Packet &pkt, Side id)
+{
+ pkt.time += delay;
+
+ if (id == SideA)
+ return sideB->sendAtomic(pkt);
+ else
+ return sideA->sendAtomic(pkt);
+}
+
+/** Function called by the port when the bus is recieving a Functional
+ * transaction.*/
+void
+Bridge::recvFunctional(Packet &pkt, Side id)
+{
+ pkt.time += delay;
+ std::list<std::pair<Packet*, Tick> >::iterator i;
+ bool pktContinue = true;
+
+ for(i = inboundA.begin(); i != inboundA.end(); ++i) {
+ if (pkt.intersect(i->first)) {
+ pktContinue &= fixPacket(pkt, *i->first);
+ }
+ }
+
+ for(i = inboundB.begin(); i != inboundB.end(); ++i) {
+ if (pkt.intersect(i->first)) {
+ pktContinue &= fixPacket(pkt, *i->first);
+ }
+ }
+
+ for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) {
+ if (pkt.intersect(i->first)) {
+ pktContinue &= fixPacket(pkt, *i->first);
+ }
+ }
+
+ for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) {
+ if (pkt.intersect(i->first)) {
+ pktContinue &= fixPacket(pkt, *i->first);
+ }
+ }
+
+ if (pktContinue) {
+ if (id == SideA)
+ sideB->sendFunctional(pkt);
+ else
+ sideA->sendFunctional(pkt);
+ }
+}
+
+/** Function called by the port when the bus is recieving a status change.*/
+void
+Bridge::recvStatusChange(Port::Status status, Side id)
+{
+ if (status == Port::Blocked || status == Port::Unblocked)
+ return ;
+
+ if (id == SideA)
+ sideB->sendStatusChange(status);
+ else
+ sideA->sendStatusChange(status);
+}
+
+void
+Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id)
+{
+ if (id == SideA)
+ sideB->getPeerAddressRanges(resp, snoop);
+ else
+ sideA->getPeerAddressRanges(resp, snoop);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
+
+ Param<int> queue_size_a;
+ Param<int> queue_size_b;
+ Param<Tick> delay;
+ Param<bool> write_ack;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Bridge)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge)
+
+ INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"),
+ INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"),
+ INIT_PARAM(delay, "The miminum delay to cross this bridge"),
+ INIT_PARAM(write_ack, "Acknowledge any writes that are received.")
+
+END_INIT_SIM_OBJECT_PARAMS(Bridge)
+
+CREATE_SIM_OBJECT(Bridge)
+{
+ return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay,
+ write_ack);
+}
+
+REGISTER_SIM_OBJECT("Bridge", Bridge)
diff --git a/mem/bridge.hh b/mem/bridge.hh
new file mode 100644
index 000000000..6bd4d81ab
--- /dev/null
+++ b/mem/bridge.hh
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file Decleration of a simple bus bridge object with no buffering
+ */
+
+#ifndef __MEM_BRIDGE_HH__
+#define __MEM_BRIDGE_HH__
+
+#include <string>
+#include <list>
+#include <inttypes.h>
+#include <queue>
+
+
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+
+class Bridge : public MemObject
+{
+ public:
+ enum Side
+ {
+ SideA,
+ SideB
+ };
+
+ protected:
+ /** Function called by the port when the bus is recieving a Timing
+ transaction.*/
+ bool recvTiming(Packet &pkt, Side id);
+
+ /** Function called by the port when the bus is recieving a Atomic
+ transaction.*/
+ Tick recvAtomic(Packet &pkt, Side id);
+
+ /** Function called by the port when the bus is recieving a Functional
+ transaction.*/
+ void recvFunctional(Packet &pkt, Side id);
+
+ /** Function called by the port when the bus is recieving a status change.*/
+ void recvStatusChange(Port::Status status, Side id);
+
+ /** Process address range request.
+ * @param resp addresses that we can respond to
+ * @param snoop addresses that we would like to snoop
+ * @param id ide of the busport that made the request.
+ */
+ void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id);
+
+
+ /** Event that the SendEvent calls when it fires. This code must reschedule
+ * the send event as required. */
+ void timerEvent();
+
+ /** Decleration of the buses port type, one will be instantiated for each
+ of the interfaces connecting to the bus. */
+ class BridgePort : public Port
+ {
+ /** A pointer to the bus to which this port belongs. */
+ Bridge *bridge;
+
+ /** A id to keep track of the intercafe ID this port is connected to. */
+ Bridge::Side side;
+
+ public:
+
+ /** Constructor for the BusPort.*/
+ BridgePort(Bridge *_bridge, Side _side)
+ : bridge(_bridge), side(_side)
+ { }
+
+ int numQueued() { return outbound.size(); }
+
+ protected:
+ /** Data this is waiting to be transmitted. */
+ std::list<std::pair<Packet*, Tick> > outbound;
+
+ void sendPkt(Packet &pkt);
+ void sendPkt(std::pair<Packet*, Tick> p);
+
+ /** When reciving a timing request from the peer port,
+ pass it to the bridge. */
+ virtual bool recvTiming(Packet &pkt)
+ { return bridge->recvTiming(pkt, side); }
+
+ /** When reciving a retry request from the peer port,
+ pass it to the bridge. */
+ virtual Packet* recvRetry();
+
+ /** When reciving a Atomic requestfrom the peer port,
+ pass it to the bridge. */
+ virtual Tick recvAtomic(Packet &pkt)
+ { return bridge->recvAtomic(pkt, side); }
+
+ /** When reciving a Functional request from the peer port,
+ pass it to the bridge. */
+ virtual void recvFunctional(Packet &pkt)
+ { bridge->recvFunctional(pkt, side); }
+
+ /** When reciving a status changefrom the peer port,
+ pass it to the bridge. */
+ virtual void recvStatusChange(Status status)
+ { bridge->recvStatusChange(status, side); }
+
+ /** When reciving a address range request the peer port,
+ pass it to the bridge. */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+ { bridge->addressRanges(resp, snoop, side); }
+
+ friend class Bridge;
+ };
+
+ class SendEvent : public Event
+ {
+ Bridge *bridge;
+
+ SendEvent(Bridge *b)
+ : Event(&mainEventQueue), bridge(b) {}
+
+ virtual void process() { bridge->timerEvent(); }
+
+ virtual const char *description() { return "bridge delay event"; }
+ friend class Bridge;
+ };
+
+ SendEvent sendEvent;
+
+ /** Sides of the bus bridges. */
+ BridgePort* sideA;
+ BridgePort* sideB;
+
+ /** inbound queues on both sides. */
+ std::list<std::pair<Packet*, Tick> > inboundA;
+ std::list<std::pair<Packet*, Tick> > inboundB;
+
+ /** The size of the queue for data coming into side a */
+ int queueSizeA;
+ int queueSizeB;
+
+ /* if the side is blocked or not. */
+ bool blockedA;
+ bool blockedB;
+
+ /** Miminum delay though this bridge. */
+ Tick delay;
+
+ /** If this bridge should acknowledge writes. */
+ bool ackWrites;
+
+ public:
+
+ /** A function used to return the port associated with this bus object. */
+ virtual Port *getPort(const std::string &if_name)
+ {
+ if (if_name == "side_a") {
+ if (sideA != NULL)
+ panic("bridge side a already connected to.");
+ sideA = new BridgePort(this, SideA);
+ return sideA;
+ } else if (if_name == "side_b") {
+ if (sideB != NULL)
+ panic("bridge side b already connected to.");
+ sideB = new BridgePort(this, SideB);
+ return sideB;
+ } else
+ return NULL;
+ }
+
+ virtual void init();
+
+ Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack)
+ : MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL),
+ queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false),
+ delay(_delay), ackWrites(write_ack)
+ {}
+
+ /** Check if the port should block/unblock after recieving/sending a packet.
+ * */
+ void blockCheck(Side id);
+
+ friend class Bridge::SendEvent;
+
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/mem/bus.cc b/mem/bus.cc
new file mode 100644
index 000000000..acc941434
--- /dev/null
+++ b/mem/bus.cc
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file Definition of a bus object.
+ */
+
+
+#include "base/trace.hh"
+#include "mem/bus.hh"
+#include "sim/builder.hh"
+
+/** Get the ranges of anyone that we are connected to. */
+void
+Bus::init()
+{
+ std::vector<Port*>::iterator intIter;
+ for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
+ (*intIter)->sendStatusChange(Port::RangeChange);
+}
+
+
+/** Function called by the port when the bus is recieving a Timing
+ * transaction.*/
+bool
+Bus::recvTiming(Packet &pkt, int id)
+{
+ return findPort(pkt.addr, id)->sendTiming(pkt);
+}
+
+Port *
+Bus::findPort(Addr addr, int id)
+{
+ /* An interval tree would be a better way to do this. --ali. */
+ int dest_id = -1;
+ int i = 0;
+ bool found = false;
+
+ while (i < portList.size() && !found)
+ {
+ if (portList[i].range == addr) {
+ dest_id = portList[i].portId;
+ found = true;
+ DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id);
+ }
+ i++;
+ }
+ if (dest_id == -1)
+ panic("Unable to find destination for addr: %llx", addr);
+
+ // we shouldn't be sending this back to where it came from
+ assert(dest_id != id);
+
+ return interfaces[dest_id];
+}
+
+/** Function called by the port when the bus is recieving a Atomic
+ * transaction.*/
+Tick
+Bus::recvAtomic(Packet &pkt, int id)
+{
+ return findPort(pkt.addr, id)->sendAtomic(pkt);
+}
+
+/** Function called by the port when the bus is recieving a Functional
+ * transaction.*/
+void
+Bus::recvFunctional(Packet &pkt, int id)
+{
+ findPort(pkt.addr, id)->sendFunctional(pkt);
+}
+
+/** Function called by the port when the bus is recieving a status change.*/
+void
+Bus::recvStatusChange(Port::Status status, int id)
+{
+ DPRINTF(Bus, "Bus %d recieved status change from device id %d\n",
+ busId, id);
+ assert(status == Port::RangeChange &&
+ "The other statuses need to be implemented.");
+
+ assert(id < interfaces.size() && id >= 0);
+ int x;
+ Port *port = interfaces[id];
+ AddrRangeList ranges;
+ AddrRangeList snoops;
+ AddrRangeIter iter;
+ std::vector<DevMap>::iterator portIter;
+
+ // Clean out any previously existent ids
+ for (portIter = portList.begin(); portIter != portList.end(); ) {
+ if (portIter->portId == id)
+ portIter = portList.erase(portIter);
+ else
+ portIter++;
+ }
+
+ port->getPeerAddressRanges(ranges, snoops);
+
+ // not dealing with snooping yet either
+ assert(snoops.size() == 0);
+ for(iter = ranges.begin(); iter != ranges.end(); iter++) {
+ DevMap dm;
+ dm.portId = id;
+ dm.range = *iter;
+
+ DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
+ dm.range.end, id);
+ portList.push_back(dm);
+ }
+ DPRINTF(MMU, "port list has %d entries\n", portList.size());
+
+ // tell all our peers that our address range has changed.
+ // Don't tell the device that caused this change, it already knows
+ for (x = 0; x < interfaces.size(); x++)
+ if (x != id)
+ interfaces[x]->sendStatusChange(Port::RangeChange);
+}
+
+void
+Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
+{
+ std::vector<DevMap>::iterator portIter;
+
+ resp.clear();
+ snoop.clear();
+
+ DPRINTF(Bus, "Bus id %d recieved address range request returning\n",
+ busId);
+ for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
+ if (portIter->portId != id) {
+ resp.push_back(portIter->range);
+ DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start,
+ portIter->range.end);
+ }
+ }
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
+
+ Param<int> bus_id;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Bus)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
+ INIT_PARAM(bus_id, "a globally unique bus id")
+END_INIT_SIM_OBJECT_PARAMS(Bus)
+
+CREATE_SIM_OBJECT(Bus)
+{
+ return new Bus(getInstanceName(), bus_id);
+}
+
+REGISTER_SIM_OBJECT("Bus", Bus)
diff --git a/mem/bus.hh b/mem/bus.hh
new file mode 100644
index 000000000..de9259a90
--- /dev/null
+++ b/mem/bus.hh
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file Decleration of a bus object.
+ */
+
+#ifndef __MEM_BUS_HH__
+#define __MEM_BUS_HH__
+
+#include <string>
+#include <list>
+#include <inttypes.h>
+
+#include "base/range.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "mem/request.hh"
+
+class Bus : public MemObject
+{
+ /** a globally unique id for this bus. */
+ int busId;
+
+ struct DevMap {
+ int portId;
+ Range<Addr> range;
+ };
+ std::vector<DevMap> portList;
+
+
+ /** Function called by the port when the bus is recieving a Timing
+ transaction.*/
+ bool recvTiming(Packet &pkt, int id);
+
+ /** Function called by the port when the bus is recieving a Atomic
+ transaction.*/
+ Tick recvAtomic(Packet &pkt, int id);
+
+ /** Function called by the port when the bus is recieving a Functional
+ transaction.*/
+ void recvFunctional(Packet &pkt, int id);
+
+ /** Function called by the port when the bus is recieving a status change.*/
+ void recvStatusChange(Port::Status status, int id);
+
+ /** Find which port connected to this bus (if any) should be given a packet
+ * with this address.
+ * @param addr Address to find port for.
+ * @param id Id of the port this packet was received from (to prevent
+ * loops)
+ * @return pointer to port that the packet should be sent out of.
+ */
+ Port *
+ Bus::findPort(Addr addr, int id);
+
+ /** Process address range request.
+ * @param resp addresses that we can respond to
+ * @param snoop addresses that we would like to snoop
+ * @param id ide of the busport that made the request.
+ */
+ void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id);
+
+
+ /** Decleration of the buses port type, one will be instantiated for each
+ of the interfaces connecting to the bus. */
+ class BusPort : public Port
+ {
+ /** A pointer to the bus to which this port belongs. */
+ Bus *bus;
+
+ /** A id to keep track of the intercafe ID this port is connected to. */
+ int id;
+
+ public:
+
+ /** Constructor for the BusPort.*/
+ BusPort(Bus *_bus, int _id)
+ : bus(_bus), id(_id)
+ { }
+
+ protected:
+
+ /** When reciving a timing request from the peer port (at id),
+ pass it to the bus. */
+ virtual bool recvTiming(Packet &pkt)
+ { return bus->recvTiming(pkt, id); }
+
+ /** When reciving a Atomic requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual Tick recvAtomic(Packet &pkt)
+ { return bus->recvAtomic(pkt, id); }
+
+ /** When reciving a Functional requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvFunctional(Packet &pkt)
+ { bus->recvFunctional(pkt, id); }
+
+ /** When reciving a status changefrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvStatusChange(Status status)
+ { bus->recvStatusChange(status, id); }
+
+ // This should return all the 'owned' addresses that are
+ // downstream from this bus, yes? That is, the union of all
+ // the 'owned' address ranges of all the other interfaces on
+ // this bus...
+ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+ { bus->addressRanges(resp, snoop, id); }
+
+ // Hack to make translating port work without changes
+ virtual int deviceBlockSize() { return 32; }
+
+ };
+
+ /** An array of pointers to the peer port interfaces
+ connected to this bus.*/
+ std::vector<Port*> interfaces;
+
+ public:
+
+ /** A function used to return the port associated with this bus object. */
+ virtual Port *getPort(const std::string &if_name)
+ {
+ // if_name ignored? forced to be empty?
+ int id = interfaces.size();
+ interfaces.push_back(new BusPort(this, id));
+ return interfaces.back();
+ }
+
+ virtual void init();
+
+ Bus(const std::string &n, int bus_id)
+ : MemObject(n), busId(bus_id) {}
+
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/mem/mem_object.cc b/mem/mem_object.cc
new file mode 100644
index 000000000..f579a0727
--- /dev/null
+++ b/mem/mem_object.cc
@@ -0,0 +1,37 @@
+/*
+ * 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 "mem/mem_object.hh"
+#include "sim/param.hh"
+
+MemObject::MemObject(const std::string &name)
+ : SimObject(name)
+{
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("MemObject", MemObject)
diff --git a/mem/mem_object.hh b/mem/mem_object.hh
new file mode 100644
index 000000000..58930eccc
--- /dev/null
+++ b/mem/mem_object.hh
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * Base Memory Object decleration.
+ */
+
+#ifndef __MEM_MEM_OBJECT_HH__
+#define __MEM_MEM_OBJECT_HH__
+
+#include "sim/sim_object.hh"
+#include "mem/port.hh"
+
+/**
+ * The base MemoryObject class, allows for an accesor function to a
+ * simobj that returns the Port.
+ */
+class MemObject : public SimObject
+{
+ public:
+ MemObject(const std::string &name);
+
+ public:
+ /** Additional function to return the Port of a memory object. */
+ virtual Port *getPort(const std::string &if_name) = 0;
+};
+
+#endif //__MEM_MEM_OBJECT_HH__
diff --git a/mem/packet.cc b/mem/packet.cc
new file mode 100644
index 000000000..ecd2a7be1
--- /dev/null
+++ b/mem/packet.cc
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * Definition of the Packet Class, a packet is a transaction occuring
+ * between a single level of the memory heirarchy (ie L1->L2).
+ */
+#include "base/misc.hh"
+#include "mem/packet.hh"
+
+
+/** delete the data pointed to in the data pointer. Ok to call to matter how
+ * data was allocted. */
+void
+Packet::deleteData() {
+ assert(staticData || dynamicData);
+ if (staticData)
+ return;
+
+ if (arrayData)
+ delete [] data;
+ else
+ delete data;
+}
+
+/** If there isn't data in the packet, allocate some. */
+void
+Packet::allocate() {
+ if (data)
+ return;
+ assert(!staticData);
+ dynamicData = true;
+ arrayData = true;
+ data = new uint8_t[size];
+}
+
+/** Do the packet modify the same addresses. */
+bool
+Packet::intersect(Packet *p) {
+ Addr s1 = addr;
+ Addr e1 = addr + size;
+ Addr s2 = p->addr;
+ Addr e2 = p->addr + p->size;
+
+ if (s1 >= s2 && s1 < e2)
+ return true;
+ if (e1 >= s2 && e1 < e2)
+ return true;
+ return false;
+}
+
+/** Minimally reset a packet so something like simple cpu can reuse it. */
+void
+Packet::reset() {
+ result = Unknown;
+ if (dynamicData) {
+ deleteData();
+ dynamicData = false;
+ arrayData = false;
+ time = curTick;
+ }
+}
+
+
+
+
+bool fixPacket(Packet &func, Packet &timing)
+{ panic("Need to implement!"); }
diff --git a/mem/packet.hh b/mem/packet.hh
new file mode 100644
index 000000000..69d00675d
--- /dev/null
+++ b/mem/packet.hh
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * Declaration of the Packet Class, a packet is a transaction occuring
+ * between a single level of the memory heirarchy (ie L1->L2).
+ */
+
+#ifndef __MEM_PACKET_HH__
+#define __MEM_PACKET_HH__
+
+#include "mem/request.hh"
+#include "arch/isa_traits.hh"
+#include "sim/root.hh"
+
+struct Packet;
+typedef Packet* PacketPtr;
+typedef uint8_t* PacketDataPtr;
+
+/** List of all commands associated with a packet. */
+enum Command
+{
+ Read,
+ Write
+};
+
+/** The result of a particular pakets request. */
+enum PacketResult
+{
+ Success,
+ BadAddress,
+ Unknown
+};
+
+class SenderState{};
+class Coherence{};
+
+/**
+ * A Packet is the structure to handle requests between two levels
+ * of the memory system. The Request is a global object that trancends
+ * all of the memory heirarchy, but at each levels interface a packet
+ * is created to transfer data/requests. For example, a request would
+ * be used to initiate a request to go to memory/IOdevices, as the request
+ * passes through the memory system several packets will be created. One
+ * will be created to go between the L1 and L2 caches and another to go to
+ * the next level and so forth.
+ *
+ * Packets are assumed to be returned in the case of a single response. If
+ * the transaction has no response, then the consumer will delete the packet.
+ */
+struct Packet
+{
+ private:
+ /** A pointer to the data being transfered. It can be differnt sizes
+ at each level of the heirarchy so it belongs in the packet,
+ not request. This may or may not be populated when a responder recieves
+ the packet. If not populated it memory should be allocated.
+ */
+ PacketDataPtr data;
+
+ /** Is the data pointer set to a value that shouldn't be freed when the
+ * packet is destroyed? */
+ bool staticData;
+ /** The data pointer points to a value that should be freed when the packet
+ * is destroyed. */
+ bool dynamicData;
+ /** the data pointer points to an array (thus delete [] ) needs to be called
+ * on it rather than simply delete.*/
+ bool arrayData;
+
+
+ public:
+ /** The address of the request, could be virtual or physical (depending on
+ cache configurations). */
+ Addr addr;
+
+ /** Flag structure to hold flags for this particular packet */
+ uint64_t flags;
+
+ /** A pointer to the overall request. */
+ RequestPtr req;
+
+ /** A virtual base opaque structure used to hold
+ coherence status messages. */
+ Coherence *coherence; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
+
+ /** A virtual base opaque structure used to hold the senders state. */
+ void *senderState; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
+
+ /** Indicates the size of the request. */
+ int size;
+
+ /** A index of the source of the transaction. */
+ short src;
+
+ /** A index to the destination of the transaction. */
+ short dest;
+
+ /** The command of the transaction. */
+ Command cmd;
+
+ /** The time this request was responded to. Used to calculate latencies. */
+ Tick time;
+
+ /** The result of the packet transaction. */
+ PacketResult result;
+
+ /** Accessor function that returns the source index of the packet. */
+ short getSrc() const { return src; }
+
+ /** Accessor function that returns the destination index of
+ the packet. */
+ short getDest() const { return dest; }
+
+ Packet()
+ : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ time(curTick), result(Unknown)
+ {}
+
+ ~Packet()
+ { deleteData(); }
+
+
+ /** Minimally reset a packet so something like simple cpu can reuse it. */
+ void reset();
+
+ /** Set the data pointer to the following value that should not be freed. */
+ template <typename T>
+ void dataStatic(T *p);
+
+ /** Set the data pointer to a value that should have delete [] called on it.
+ */
+ template <typename T>
+ void dataDynamicArray(T *p);
+
+ /** set the data pointer to a value that should have delete called on it. */
+ template <typename T>
+ void dataDynamic(T *p);
+
+ /** return the value of what is pointed to in the packet. */
+ template <typename T>
+ T get();
+
+ /** get a pointer to the data ptr. */
+ template <typename T>
+ T* getPtr();
+
+ /** set the value in the data pointer to v. */
+ template <typename T>
+ void set(T v);
+
+ /** delete the data pointed to in the data pointer. Ok to call to matter how
+ * data was allocted. */
+ void deleteData();
+
+ /** If there isn't data in the packet, allocate some. */
+ void allocate();
+
+ /** Do the packet modify the same addresses. */
+ bool intersect(Packet *p);
+};
+
+bool fixPacket(Packet &func, Packet &timing);
+#endif //__MEM_PACKET_HH
diff --git a/mem/page_table.cc b/mem/page_table.cc
new file mode 100644
index 000000000..c4e1ea193
--- /dev/null
+++ b/mem/page_table.cc
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/**
+ * @file
+ * Definitions of page table.
+ */
+#include <string>
+#include <map>
+#include <fstream>
+
+#include "arch/faults.hh"
+#include "base/bitfield.hh"
+#include "base/intmath.hh"
+#include "base/trace.hh"
+#include "mem/page_table.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace TheISA;
+
+PageTable::PageTable(System *_system, Addr _pageSize)
+ : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
+ system(_system)
+{
+ assert(isPowerOf2(pageSize));
+}
+
+PageTable::~PageTable()
+{
+}
+
+Fault
+PageTable::page_check(Addr addr, int size) const
+{
+ if (size < sizeof(uint64_t)) {
+ if (!isPowerOf2(size)) {
+ panic("Invalid request size!\n");
+ return genMachineCheckFault();
+ }
+
+ if ((size - 1) & addr)
+ return genAlignmentFault();
+ }
+ else {
+ if ((addr & (VMPageSize - 1)) + size > VMPageSize) {
+ panic("Invalid request size!\n");
+ return genMachineCheckFault();
+ }
+
+ if ((sizeof(uint64_t) - 1) & addr)
+ return genAlignmentFault();
+ }
+
+ return NoFault;
+}
+
+
+
+
+void
+PageTable::allocate(Addr vaddr, int size)
+{
+ // starting address must be page aligned
+ assert(pageOffset(vaddr) == 0);
+
+ for (; size > 0; size -= pageSize, vaddr += pageSize) {
+ std::map<Addr,Addr>::iterator iter = pTable.find(vaddr);
+
+ if (iter != pTable.end()) {
+ // already mapped
+ fatal("PageTable::allocate: address 0x%x already mapped", vaddr);
+ }
+
+ pTable[vaddr] = system->new_page();
+ }
+}
+
+
+
+bool
+PageTable::translate(Addr vaddr, Addr &paddr)
+{
+ Addr page_addr = pageAlign(vaddr);
+ std::map<Addr,Addr>::iterator iter = pTable.find(page_addr);
+
+ if (iter == pTable.end()) {
+ return false;
+ }
+
+ paddr = iter->second + pageOffset(vaddr);
+ return true;
+}
+
+
+Fault
+PageTable::translate(RequestPtr &req)
+{
+ Addr paddr;
+ assert(pageAlign(req->getVaddr() + req->getSize() - 1)
+ == pageAlign(req->getVaddr()));
+ if (!translate(req->getVaddr(), paddr)) {
+ return genMachineCheckFault();
+ }
+ req->setPaddr(paddr);
+ return page_check(req->getPaddr(), req->getSize());
+}
diff --git a/mem/page_table.hh b/mem/page_table.hh
new file mode 100644
index 000000000..26248261a
--- /dev/null
+++ b/mem/page_table.hh
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/**
+ * @file
+ * Declaration of a non-full system Page Table.
+ */
+
+#ifndef __PAGE_TABLE__
+#define __PAGE_TABLE__
+
+#include <string>
+#include <map>
+
+#include "arch/isa_traits.hh"
+#include "base/trace.hh"
+#include "mem/request.hh"
+#include "mem/packet.hh"
+#include "sim/sim_object.hh"
+
+class System;
+
+/**
+ * Page Table Decleration.
+ */
+class PageTable
+{
+ protected:
+ std::map<Addr,Addr> pTable;
+
+ const Addr pageSize;
+ const Addr offsetMask;
+
+ System *system;
+
+ public:
+
+ PageTable(System *_system, Addr _pageSize = TheISA::VMPageSize);
+
+ ~PageTable();
+
+ Addr pageAlign(Addr a) { return (a & ~offsetMask); }
+ Addr pageOffset(Addr a) { return (a & offsetMask); }
+
+ Fault page_check(Addr addr, int size) const;
+
+ void allocate(Addr vaddr, int size);
+
+ /**
+ * Translate function
+ * @param vaddr The virtual address.
+ * @return Physical address from translation.
+ */
+ bool translate(Addr vaddr, Addr &paddr);
+
+ /**
+ * Perform a translation on the memory request, fills in paddr
+ * field of mem_req.
+ * @param req The memory request.
+ */
+ Fault translate(RequestPtr &req);
+
+};
+
+#endif
diff --git a/mem/physical.cc b/mem/physical.cc
new file mode 100644
index 000000000..a9cefc70b
--- /dev/null
+++ b/mem/physical.cc
@@ -0,0 +1,368 @@
+/*
+ * 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/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include <cstdio>
+#include <iostream>
+#include <string>
+
+
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "mem/packet_impl.hh"
+#include "mem/physical.hh"
+#include "sim/host.hh"
+#include "sim/builder.hh"
+#include "sim/eventq.hh"
+#include "arch/isa_traits.hh"
+
+
+using namespace std;
+using namespace TheISA;
+
+PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet &pkt, MemoryPort* _m)
+ : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
+{
+
+ this->setFlags(AutoDelete);
+}
+
+void
+PhysicalMemory::MemResponseEvent::process()
+{
+ memoryPort->sendTiming(pkt);
+}
+
+const char *
+PhysicalMemory::MemResponseEvent::description()
+{
+ return "Physical Memory Timing Access respnse event";
+}
+
+PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
+ : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
+{
+ // Hardcoded to 128 MB for now.
+ pmem_size = 1 << 27;
+
+ if (pmem_size % TheISA::PageBytes != 0)
+ panic("Memory Size not divisible by page size\n");
+
+ int map_flags = MAP_ANON | MAP_PRIVATE;
+ pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+ map_flags, -1, 0);
+
+ if (pmem_addr == (void *)MAP_FAILED) {
+ perror("mmap");
+ fatal("Could not mmap!\n");
+ }
+
+ page_ptr = 0;
+}
+
+void
+PhysicalMemory::init()
+{
+ if (!port)
+ panic("PhysicalMemory not connected to anything!");
+ port->sendStatusChange(Port::RangeChange);
+}
+
+PhysicalMemory::~PhysicalMemory()
+{
+ if (pmem_addr)
+ munmap(pmem_addr, pmem_size);
+ //Remove memPorts?
+}
+
+Addr
+PhysicalMemory::new_page()
+{
+ Addr return_addr = page_ptr << LogVMPageSize;
+ return_addr += base_addr;
+
+ ++page_ptr;
+ return return_addr;
+}
+
+int
+PhysicalMemory::deviceBlockSize()
+{
+ //Can accept anysize request
+ return 0;
+}
+
+bool
+PhysicalMemory::doTimingAccess (Packet &pkt, MemoryPort* memoryPort)
+{
+ doFunctionalAccess(pkt);
+
+ MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
+ response->schedule(curTick + lat);
+
+ return true;
+}
+
+Tick
+PhysicalMemory::doAtomicAccess(Packet &pkt)
+{
+ doFunctionalAccess(pkt);
+ pkt.time = curTick + lat;
+ return curTick + lat;
+}
+
+void
+PhysicalMemory::doFunctionalAccess(Packet &pkt)
+{
+ assert(pkt.addr + pkt.size < pmem_size);
+
+ switch (pkt.cmd) {
+ case Read:
+ memcpy(pkt.getPtr<uint8_t>(), pmem_addr + pkt.addr - base_addr,
+ pkt.size);
+ break;
+ case Write:
+ memcpy(pmem_addr + pkt.addr - base_addr, pkt.getPtr<uint8_t>(),
+ pkt.size);
+ break;
+ default:
+ panic("unimplemented");
+ }
+
+ pkt.result = Success;
+}
+
+Port *
+PhysicalMemory::getPort(const std::string &if_name)
+{
+ if (if_name == "") {
+ if (port != NULL)
+ panic("PhysicalMemory::getPort: additional port requested to memory!");
+ port = new MemoryPort(this);
+ return port;
+ } else if (if_name == "functional") {
+ /* special port for functional writes at startup. */
+ return new MemoryPort(this);
+ } else {
+ panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
+ }
+}
+
+void
+PhysicalMemory::recvStatusChange(Port::Status status)
+{
+}
+
+PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
+ : memory(_memory)
+{ }
+
+void
+PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
+{
+ memory->recvStatusChange(status);
+}
+
+void
+PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+{
+ memory->getAddressRanges(resp, snoop);
+}
+
+void
+PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+{
+ snoop.clear();
+ resp.clear();
+ resp.push_back(RangeSize(base_addr, pmem_size));
+}
+
+int
+PhysicalMemory::MemoryPort::deviceBlockSize()
+{
+ return memory->deviceBlockSize();
+}
+
+bool
+PhysicalMemory::MemoryPort::recvTiming(Packet &pkt)
+{
+ return memory->doTimingAccess(pkt, this);
+}
+
+Tick
+PhysicalMemory::MemoryPort::recvAtomic(Packet &pkt)
+{
+ return memory->doAtomicAccess(pkt);
+}
+
+void
+PhysicalMemory::MemoryPort::recvFunctional(Packet &pkt)
+{
+ memory->doFunctionalAccess(pkt);
+}
+
+
+
+void
+PhysicalMemory::serialize(ostream &os)
+{
+ gzFile compressedMem;
+ string filename = name() + ".physmem";
+
+ SERIALIZE_SCALAR(pmem_size);
+ SERIALIZE_SCALAR(filename);
+
+ // write memory file
+ string thefile = Checkpoint::dir() + "/" + filename.c_str();
+ int fd = creat(thefile.c_str(), 0664);
+ if (fd < 0) {
+ perror("creat");
+ fatal("Can't open physical memory checkpoint file '%s'\n", filename);
+ }
+
+ compressedMem = gzdopen(fd, "wb");
+ if (compressedMem == NULL)
+ fatal("Insufficient memory to allocate compression state for %s\n",
+ filename);
+
+ if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) {
+ fatal("Write failed on physical memory checkpoint file '%s'\n",
+ filename);
+ }
+
+ if (gzclose(compressedMem))
+ fatal("Close failed on physical memory checkpoint file '%s'\n",
+ filename);
+}
+
+void
+PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
+{
+ gzFile compressedMem;
+ long *tempPage;
+ long *pmem_current;
+ uint64_t curSize;
+ uint32_t bytesRead;
+ const int chunkSize = 16384;
+
+
+ // unmap file that was mmaped in the constructor
+ munmap(pmem_addr, pmem_size);
+
+ string filename;
+
+ UNSERIALIZE_SCALAR(pmem_size);
+ UNSERIALIZE_SCALAR(filename);
+
+ filename = cp->cptDir + "/" + filename;
+
+ // mmap memoryfile
+ int fd = open(filename.c_str(), O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ fatal("Can't open physical memory checkpoint file '%s'", filename);
+ }
+
+ compressedMem = gzdopen(fd, "rb");
+ if (compressedMem == NULL)
+ fatal("Insufficient memory to allocate compression state for %s\n",
+ filename);
+
+
+ pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+
+ if (pmem_addr == (void *)MAP_FAILED) {
+ perror("mmap");
+ fatal("Could not mmap physical memory!\n");
+ }
+
+ curSize = 0;
+ tempPage = (long*)malloc(chunkSize);
+ if (tempPage == NULL)
+ fatal("Unable to malloc memory to read file %s\n", filename);
+
+ /* Only copy bytes that are non-zero, so we don't give the VM system hell */
+ while (curSize < pmem_size) {
+ bytesRead = gzread(compressedMem, tempPage, chunkSize);
+ if (bytesRead != chunkSize && bytesRead != pmem_size - curSize)
+ fatal("Read failed on physical memory checkpoint file '%s'"
+ " got %d bytes, expected %d or %d bytes\n",
+ filename, bytesRead, chunkSize, pmem_size-curSize);
+
+ assert(bytesRead % sizeof(long) == 0);
+
+ for (int x = 0; x < bytesRead/sizeof(long); x++)
+ {
+ if (*(tempPage+x) != 0) {
+ pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long));
+ *pmem_current = *(tempPage+x);
+ }
+ }
+ curSize += bytesRead;
+ }
+
+ free(tempPage);
+
+ if (gzclose(compressedMem))
+ fatal("Close failed on physical memory checkpoint file '%s'\n",
+ filename);
+
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+ Param<string> file;
+ Param<Range<Addr> > range;
+ Param<Tick> latency;
+
+END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+ INIT_PARAM_DFLT(file, "memory mapped file", ""),
+ INIT_PARAM(range, "Device Address Range"),
+ INIT_PARAM(latency, "Memory access latency")
+
+END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+CREATE_SIM_OBJECT(PhysicalMemory)
+{
+
+ return new PhysicalMemory(getInstanceName(), latency);
+}
+
+REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
diff --git a/mem/physical.hh b/mem/physical.hh
new file mode 100644
index 000000000..f87683c45
--- /dev/null
+++ b/mem/physical.hh
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+/* @file
+ */
+
+#ifndef __PHYSICAL_MEMORY_HH__
+#define __PHYSICAL_MEMORY_HH__
+
+#include "base/range.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+#include <map>
+#include <string>
+
+//
+// Functional model for a contiguous block of physical memory. (i.e. RAM)
+//
+class PhysicalMemory : public MemObject
+{
+ class MemoryPort : public Port
+ {
+ PhysicalMemory *memory;
+
+ public:
+
+ MemoryPort(PhysicalMemory *_memory);
+
+ protected:
+
+ virtual bool recvTiming(Packet &pkt);
+
+ virtual Tick recvAtomic(Packet &pkt);
+
+ virtual void recvFunctional(Packet &pkt);
+
+ virtual void recvStatusChange(Status status);
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop);
+
+ virtual int deviceBlockSize();
+ };
+
+ int numPorts;
+
+
+ struct MemResponseEvent : public Event
+ {
+ Packet &pkt;
+ MemoryPort *memoryPort;
+
+ MemResponseEvent(Packet &pkt, MemoryPort *memoryPort);
+ void process();
+ const char *description();
+ };
+
+ private:
+ // prevent copying of a MainMemory object
+ PhysicalMemory(const PhysicalMemory &specmem);
+ const PhysicalMemory &operator=(const PhysicalMemory &specmem);
+
+ protected:
+ Addr base_addr;
+ Addr pmem_size;
+ uint8_t *pmem_addr;
+ MemoryPort *port;
+ int page_ptr;
+ Tick lat;
+
+ public:
+ Addr new_page();
+ uint64_t size() { return pmem_size; }
+
+ public:
+ PhysicalMemory(const std::string &n, Tick latency);
+ virtual ~PhysicalMemory();
+
+ public:
+ int deviceBlockSize();
+ void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+ virtual Port *getPort(const std::string &if_name);
+ void virtual init();
+
+ // fast back-door memory access for vtophys(), remote gdb, etc.
+ // uint64_t phys_read_qword(Addr addr) const;
+ private:
+ bool doTimingAccess(Packet &pkt, MemoryPort *memoryPort);
+ Tick doAtomicAccess(Packet &pkt);
+ void doFunctionalAccess(Packet &pkt);
+
+ void recvStatusChange(Port::Status status);
+
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif //__PHYSICAL_MEMORY_HH__
diff --git a/mem/port.cc b/mem/port.cc
new file mode 100644
index 000000000..32031d96c
--- /dev/null
+++ b/mem/port.cc
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file Port object definitions.
+ */
+
+#include "base/chunk_generator.hh"
+#include "mem/port.hh"
+
+void
+Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
+{
+ Request req(false);
+ Packet pkt;
+ pkt.req = &req;
+ pkt.cmd = cmd;
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ req.setPaddr(pkt.addr = gen.addr());
+ req.setSize(pkt.size = gen.size());
+ pkt.dataStatic(p);
+ sendFunctional(pkt);
+ p += gen.size();
+ }
+}
+
+void
+Port::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Write);
+}
+
+void
+Port::readBlob(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Read);
+}
+
+void
+Port::memsetBlob(Addr addr, uint8_t val, int size)
+{
+ // quick and dirty...
+ uint8_t *buf = new uint8_t[size];
+
+ memset(buf, val, size);
+ blobHelper(addr, buf, size, Write);
+
+ delete [] buf;
+}
diff --git a/mem/port.hh b/mem/port.hh
new file mode 100644
index 000000000..2ab2806c9
--- /dev/null
+++ b/mem/port.hh
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * Port Object Decleration. Ports are used to interface memory objects to
+ * each other. They will always come in pairs, and we refer to the other
+ * port object as the peer. These are used to make the design more
+ * modular so that a specific interface between every type of objcet doesn't
+ * have to be created.
+ */
+
+#ifndef __MEM_PORT_HH__
+#define __MEM_PORT_HH__
+
+#include <list>
+#include <inttypes.h>
+
+#include "base/misc.hh"
+#include "base/range.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
+
+/** This typedef is used to clean up the parameter list of
+ * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared
+ * outside the Port object since it's also used by some mem objects.
+ * Eventually we should move this typedef to wherever Addr is
+ * defined.
+ */
+
+typedef std::list<Range<Addr> > AddrRangeList;
+typedef std::list<Range<Addr> >::iterator AddrRangeIter;
+
+/**
+ * Ports are used to interface memory objects to
+ * each other. They will always come in pairs, and we refer to the other
+ * port object as the peer. These are used to make the design more
+ * modular so that a specific interface between every type of objcet doesn't
+ * have to be created.
+ *
+ * Recv accesor functions are being called from the peer interface.
+ * Send accessor functions are being called from the device the port is
+ * associated with, and it will call the peer recv. accessor function.
+ */
+class Port
+{
+ public:
+
+ virtual ~Port() {};
+ // mey be better to use subclasses & RTTI?
+ /** Holds the ports status. Keeps track if it is blocked, or has
+ calculated a range change. */
+ enum Status {
+ Blocked,
+ Unblocked,
+ RangeChange
+ };
+
+ private:
+
+ /** A pointer to the peer port. Ports always come in pairs, that way they
+ can use a standardized interface to communicate between different
+ memory objects. */
+ Port *peer;
+
+ public:
+
+ /** Function to set the pointer for the peer port.
+ @todo should be called by the configuration stuff (python).
+ */
+ void setPeer(Port *port) { peer = port; }
+
+ /** Function to set the pointer for the peer port.
+ @todo should be called by the configuration stuff (python).
+ */
+ Port *getPeer() { return peer; }
+
+ protected:
+
+ /** These functions are protected because they should only be
+ * called by a peer port, never directly by any outside object. */
+
+ /** Called to recive a timing call from the peer port. */
+ virtual bool recvTiming(Packet &pkt) = 0;
+
+ /** Called to recive a atomic call from the peer port. */
+ virtual Tick recvAtomic(Packet &pkt) = 0;
+
+ /** Called to recive a functional call from the peer port. */
+ virtual void recvFunctional(Packet &pkt) = 0;
+
+ /** Called to recieve a status change from the peer port. */
+ virtual void recvStatusChange(Status status) = 0;
+
+ /** Called by a peer port if the send was unsuccesful, and had to
+ wait. This shouldn't be valid for response paths (IO Devices).
+ so it is set to panic if it isn't already defined.
+ */
+ virtual Packet *recvRetry() { panic("??"); }
+
+ /** Called by a peer port in order to determine the block size of the
+ device connected to this port. It sometimes doesn't make sense for
+ this function to be called, a DMA interface doesn't really have a
+ block size, so it is defaulted to a panic.
+ */
+ virtual int deviceBlockSize() { panic("??"); }
+
+ /** The peer port is requesting us to reply with a list of the ranges we
+ are responsible for.
+ @param resp is a list of ranges responded to
+ @param snoop is a list of ranges snooped
+ */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { panic("??"); }
+
+ public:
+
+ /** Function called by associated memory device (cache, memory, iodevice)
+ in order to send a timing request to the port. Simply calls the peer
+ port receive function.
+ @return This function returns if the send was succesful in it's
+ recieve. If it was a failure, then the port will wait for a recvRetry
+ at which point it can issue a successful sendTiming. This is used in
+ case a cache has a higher priority request come in while waiting for
+ the bus to arbitrate.
+ */
+ bool sendTiming(Packet &pkt) { return peer->recvTiming(pkt); }
+
+ /** Function called by the associated device to send an atomic access,
+ an access in which the data is moved and the state is updated in one
+ cycle, without interleaving with other memory accesses.
+ */
+ Tick sendAtomic(Packet &pkt)
+ { return peer->recvAtomic(pkt); }
+
+ /** Function called by the associated device to send a functional access,
+ an access in which the data is instantly updated everywhere in the
+ memory system, without affecting the current state of any block or
+ moving the block.
+ */
+ void sendFunctional(Packet &pkt)
+ { return peer->recvFunctional(pkt); }
+
+ /** Called by the associated device to send a status change to the device
+ connected to the peer interface.
+ */
+ void sendStatusChange(Status status) {peer->recvStatusChange(status); }
+
+ /** When a timing access doesn't return a success, some time later the
+ Retry will be sent.
+ */
+ Packet *sendRetry() { return peer->recvRetry(); }
+
+ /** Called by the associated device if it wishes to find out the blocksize
+ of the device on attached to the peer port.
+ */
+ int peerBlockSize() { return peer->deviceBlockSize(); }
+
+ /** Called by the associated device if it wishes to find out the address
+ ranges connected to the peer ports devices.
+ */
+ void getPeerAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+ { peer->getDeviceAddressRanges(resp, snoop); }
+
+ /** This function is a wrapper around sendFunctional()
+ that breaks a larger, arbitrarily aligned access into
+ appropriate chunks. The default implementation can use
+ getBlockSize() to determine the block size and go from there.
+ */
+ virtual void readBlob(Addr addr, uint8_t *p, int size);
+
+ /** This function is a wrapper around sendFunctional()
+ that breaks a larger, arbitrarily aligned access into
+ appropriate chunks. The default implementation can use
+ getBlockSize() to determine the block size and go from there.
+ */
+ virtual void writeBlob(Addr addr, uint8_t *p, int size);
+
+ /** Fill size bytes starting at addr with byte value val. This
+ should not need to be virtual, since it can be implemented in
+ terms of writeBlob(). However, it shouldn't be
+ performance-critical either, so it could be if we wanted to.
+ */
+ virtual void memsetBlob(Addr addr, uint8_t val, int size);
+
+ private:
+
+ /** Internal helper function for read/writeBlob().
+ */
+ void blobHelper(Addr addr, uint8_t *p, int size, Command cmd);
+};
+
+/** A simple functional port that is only meant for one way communication to
+ * physical memory. It is only meant to be used to load data into memory before
+ * the simulation begins.
+ */
+
+class FunctionalPort : public Port
+{
+ public:
+ virtual bool recvTiming(Packet &pkt) { panic("FuncPort is UniDir"); }
+ virtual Tick recvAtomic(Packet &pkt) { panic("FuncPort is UniDir"); }
+ virtual void recvFunctional(Packet &pkt) { panic("FuncPort is UniDir"); }
+ virtual void recvStatusChange(Status status) {}
+
+ template <typename T>
+ inline void write(Addr addr, T d)
+ {
+ writeBlob(addr, (uint8_t*)&d, sizeof(T));
+ }
+
+ template <typename T>
+ inline T read(Addr addr)
+ {
+ T d;
+ readBlob(addr, (uint8_t*)&d, sizeof(T));
+ return d;
+ }
+};
+
+#endif //__MEM_PORT_HH__
diff --git a/mem/request.hh b/mem/request.hh
new file mode 100644
index 000000000..903e7503c
--- /dev/null
+++ b/mem/request.hh
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file Decleration of a request, the overall memory request consisting of
+ the parts of the request that are persistent throughout the transaction.
+ */
+
+#ifndef __MEM_REQUEST_HH__
+#define __MEM_REQUEST_HH__
+
+#include "arch/isa_traits.hh"
+
+class Request;
+
+typedef Request* RequestPtr;
+
+/** The request is a Load locked/store conditional. */
+const unsigned LOCKED = 0x001;
+/** The virtual address is also the physical address. */
+const unsigned PHYSICAL = 0x002;
+/** The request is an ALPHA VPTE pal access (hw_ld). */
+const unsigned VPTE = 0x004;
+/** Use the alternate mode bits in ALPHA. */
+const unsigned ALTMODE = 0x008;
+/** The request is to an uncacheable address. */
+const unsigned UNCACHEABLE = 0x010;
+/** The request should not cause a page fault. */
+const unsigned NO_FAULT = 0x020;
+/** The request should be prefetched into the exclusive state. */
+const unsigned PF_EXCLUSIVE = 0x100;
+/** The request should be marked as LRU. */
+const unsigned EVICT_NEXT = 0x200;
+/** The request should ignore unaligned access faults */
+const unsigned NO_ALIGN_FAULT = 0x400;
+
+class Request
+{
+ //@todo Make Accesor functions, make these private.
+ public:
+ /** Constructor, needs a bool to signify if it is/isn't Cpu Request. */
+ Request(bool isCpu);
+
+ /** reset the request to it's initial state so it can be reused.*/
+ void resetAll(bool isCpu);
+
+ /** reset the request's addrs times, etc, so but not everything to same
+ * time. */
+ void resetMin();
+
+//First non-cpu request fields
+ private:
+ /** The physical address of the request. */
+ Addr paddr;
+ /** Wether or not paddr is valid (has been written yet). */
+ bool validPaddr;
+
+ /** The size of the request. */
+ int size;
+ /** Wether or not size is valid (has been written yet). */
+ bool validSize;
+
+ /** The time this request was started. Used to calculate latencies. */
+ Tick time;
+ /** Wether or not time is valid (has been written yet). */
+ bool validTime;
+
+ /** Destination address if this is a block copy. */
+ Addr copyDest;
+ /** Wether or not copyDest is valid (has been written yet). */
+ bool validCopyDest;
+
+ /** Flag structure for the request. */
+ uint32_t flags;
+ /** Wether or not flags is valid (has been written yet). */
+ bool validFlags;
+
+//Accsesors for non-cpu request fields
+ public:
+ /** Accesor for paddr. */
+ Addr getPaddr();
+ /** Accesor for paddr. */
+ void setPaddr(Addr _paddr);
+
+ /** Accesor for size. */
+ int getSize();
+ /** Accesor for size. */
+ void setSize(int _size);
+
+ /** Accesor for time. */
+ Tick getTime();
+ /** Accesor for time. */
+ void setTime(Tick _time);
+
+ /** Accesor for copy dest. */
+ Addr getCopyDest();
+ /** Accesor for copy dest. */
+ void setCopyDest(Addr _copyDest);
+
+ /** Accesor for flags. */
+ uint32_t getFlags();
+ /** Accesor for paddr. */
+ void setFlags(uint32_t _flags);
+
+//Now cpu-request fields
+ private:
+ /** Bool to signify if this is a cpuRequest. */
+ bool cpuReq;
+
+ /** The virtual address of the request. */
+ Addr vaddr;
+ /** Wether or not the vaddr is valid. */
+ bool validVaddr;
+
+ /** The address space ID. */
+ int asid;
+ /** Wether or not the asid is valid. */
+ bool validAsid;
+
+ /** The return value of store conditional. */
+ uint64_t scResult;
+ /** Wether or not the sc result is valid. */
+ bool validScResult;
+
+ /** The cpu number for statistics. */
+ int cpuNum;
+ /** Wether or not the cpu number is valid. */
+ bool validCpuNum;
+
+ /** The requesting thread id. */
+ int threadNum;
+ /** Wether or not the thread id is valid. */
+ bool validThreadNum;
+
+ /** program counter of initiating access; for tracing/debugging */
+ Addr pc;
+ /** Wether or not the pc is valid. */
+ bool validPC;
+
+//Accessor Functions for cpu request fields
+ public:
+ /** Accesor function to determine if this is a cpu request or not.*/
+ bool isCpuRequest();
+
+ /** Accesor function for vaddr.*/
+ Addr getVaddr();
+ /** Accesor function for vaddr.*/
+ void setVaddr(Addr _vaddr);
+
+ /** Accesor function for asid.*/
+ int getAsid();
+ /** Accesor function for asid.*/
+ void setAsid(int _asid);
+
+ /** Accesor function for store conditional return value.*/
+ uint64_t getScResult();
+ /** Accesor function for store conditional return value.*/
+ void setScResult(uint64_t _scResult);
+
+ /** Accesor function for cpu number.*/
+ int getCpuNum();
+ /** Accesor function for cpu number.*/
+ void setCpuNum(int _cpuNum);
+
+ /** Accesor function for thread number.*/
+ int getThreadNum();
+ /** Accesor function for thread number.*/
+ void setThreadNum(int _threadNum);
+
+ /** Accesor function for pc.*/
+ Addr getPC();
+ /** Accesor function for pc.*/
+ void setPC(Addr _pc);
+
+};
+
+#endif // __MEM_REQUEST_HH__
diff --git a/mem/translating_port.cc b/mem/translating_port.cc
new file mode 100644
index 000000000..5dfeaff31
--- /dev/null
+++ b/mem/translating_port.cc
@@ -0,0 +1,186 @@
+/*
+ * 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 <string>
+#include "base/chunk_generator.hh"
+#include "mem/port.hh"
+#include "mem/translating_port.hh"
+#include "mem/page_table.hh"
+
+using namespace TheISA;
+
+TranslatingPort::TranslatingPort(PageTable *p_table, bool alloc)
+ : pTable(p_table), allocating(alloc)
+{ }
+
+TranslatingPort::~TranslatingPort()
+{ }
+
+bool
+TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(),paddr))
+ return false;
+
+ Port::readBlob(paddr, p + prevSize, gen.size());
+ prevSize += gen.size();
+ }
+
+ return true;
+}
+
+void
+TranslatingPort::readBlob(Addr addr, uint8_t *p, int size)
+{
+ if (!tryReadBlob(addr, p, size))
+ fatal("readBlob(0x%x, ...) failed", addr);
+}
+
+
+bool
+TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size)
+{
+
+ Addr paddr;
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(), paddr)) {
+ if (allocating) {
+ pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ pTable->translate(gen.addr(), paddr);
+ } else {
+ return false;
+ }
+ }
+
+ Port::writeBlob(paddr, p + prevSize, gen.size());
+ prevSize += gen.size();
+ }
+
+ return true;
+}
+
+
+void
+TranslatingPort::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ if (!tryWriteBlob(addr, p, size))
+ fatal("writeBlob(0x%x, ...) failed", addr);
+}
+
+bool
+TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size)
+{
+ Addr paddr;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(), paddr)) {
+ if (allocating) {
+ pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ pTable->translate(gen.addr(), paddr);
+ } else {
+ return false;
+ }
+ }
+
+ Port::memsetBlob(paddr, val, gen.size());
+ }
+
+ return true;
+}
+
+void
+TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size)
+{
+ if (!tryMemsetBlob(addr, val, size))
+ fatal("memsetBlob(0x%x, ...) failed", addr);
+}
+
+
+bool
+TranslatingPort::tryWriteString(Addr addr, const char *str)
+{
+ Addr paddr,vaddr;
+ uint8_t c;
+
+ vaddr = addr;
+
+ do {
+ c = *str++;
+ if (!pTable->translate(vaddr++,paddr))
+ return false;
+
+ Port::writeBlob(paddr, &c, 1);
+ } while (c);
+
+ return true;
+}
+
+void
+TranslatingPort::writeString(Addr addr, const char *str)
+{
+ if (!tryWriteString(addr, str))
+ fatal("writeString(0x%x, ...) failed", addr);
+}
+
+bool
+TranslatingPort::tryReadString(std::string &str, Addr addr)
+{
+ Addr paddr,vaddr;
+ uint8_t c;
+
+ vaddr = addr;
+
+ do {
+ if (!pTable->translate(vaddr++,paddr))
+ return false;
+
+ Port::readBlob(paddr, &c, 1);
+ str += c;
+ } while (c);
+
+ return true;
+}
+
+void
+TranslatingPort::readString(std::string &str, Addr addr)
+{
+ if (!tryReadString(str, addr))
+ fatal("readString(0x%x, ...) failed", addr);
+}
+
diff --git a/mem/translating_port.hh b/mem/translating_port.hh
new file mode 100644
index 000000000..7611ac3c7
--- /dev/null
+++ b/mem/translating_port.hh
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef __MEM_TRANSLATING_PROT_HH__
+#define __MEM_TRANSLATING_PROT_HH__
+
+#include "mem/port.hh"
+
+class PageTable;
+
+class TranslatingPort : public FunctionalPort
+{
+ private:
+ PageTable *pTable;
+ bool allocating;
+
+ TranslatingPort(const TranslatingPort &specmem);
+ const TranslatingPort &operator=(const TranslatingPort &specmem);
+
+ public:
+ TranslatingPort(PageTable *p_table, bool alloc = false);
+ virtual ~TranslatingPort();
+
+ public:
+ bool tryReadBlob(Addr addr, uint8_t *p, int size);
+ bool tryWriteBlob(Addr addr, uint8_t *p, int size);
+ bool tryMemsetBlob(Addr addr, uint8_t val, int size);
+ bool tryWriteString(Addr addr, const char *str);
+ bool tryReadString(std::string &str, Addr addr);
+
+ virtual void readBlob(Addr addr, uint8_t *p, int size);
+ virtual void writeBlob(Addr addr, uint8_t *p, int size);
+ virtual void memsetBlob(Addr addr, uint8_t val, int size);
+ void writeString(Addr addr, const char *str);
+ void readString(std::string &str, Addr addr);
+
+};
+
+#endif
diff --git a/mem/vport.cc b/mem/vport.cc
new file mode 100644
index 000000000..cc569acf3
--- /dev/null
+++ b/mem/vport.cc
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file Port object definitions.
+ */
+
+#include "base/chunk_generator.hh"
+#include "mem/vport.hh"
+
+void
+VirtualPort::readBlob(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done();
+ gen.next())
+ {
+ if (xc)
+ paddr = TheISA::vtophys(xc,gen.addr());
+ else
+ paddr = TheISA::vtophys(gen.addr());
+
+ FunctionalPort::readBlob(paddr, p, gen.size());
+ p += gen.size();
+ }
+}
+
+void
+VirtualPort::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done();
+ gen.next())
+ {
+ if (xc)
+ paddr = TheISA::vtophys(xc,gen.addr());
+ else
+ paddr = TheISA::vtophys(gen.addr());
+
+ FunctionalPort::writeBlob(paddr, p, gen.size());
+ p += gen.size();
+ }
+}
+
diff --git a/mem/vport.hh b/mem/vport.hh
new file mode 100644
index 000000000..fbc230ba3
--- /dev/null
+++ b/mem/vport.hh
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * Virtual Port Object Decleration. These ports incorporate some translation
+ * into their access methods. Thus you can use one to read and write data
+ * to/from virtual addresses.
+ */
+
+#ifndef __MEM_VPORT_HH__
+#define __MEM_VPORT_HH__
+
+#include "mem/port.hh"
+#include "config/full_system.hh"
+#include "arch/vtophys.hh"
+
+
+/** A class that translates a virtual address to a physical address and then
+ * calls the above read/write functions. If an execution context is provided the
+ * address can alway be translated, If not it can only be translated if it is a
+ * simple address masking operation (such as alpha super page accesses).
+ */
+
+class VirtualPort : public FunctionalPort
+{
+ private:
+ ExecContext *xc;
+
+ public:
+ VirtualPort(ExecContext *_xc = NULL)
+ : xc(_xc)
+ {}
+
+ /** Return true if we have an exec context. This is used to prevent someone
+ * from accidently deleting the cpus statically allocated vport.
+ * @return true if an execution context isn't valid
+ */
+ bool nullExecContext() { return xc != NULL; }
+
+ /** Version of readblob that translates virt->phys and deals
+ * with page boundries. */
+ virtual void readBlob(Addr addr, uint8_t *p, int size);
+
+ /** Version of writeBlob that translates virt->phys and deals
+ * with page boundries. */
+ virtual void writeBlob(Addr addr, uint8_t *p, int size);
+};
+
+#endif //__MEM_VPORT_HH__
+
diff --git a/python/m5/objects/AlphaConsole.py b/python/m5/objects/AlphaConsole.py
index f8f034682..68e6089ab 100644
--- a/python/m5/objects/AlphaConsole.py
+++ b/python/m5/objects/AlphaConsole.py
@@ -1,9 +1,9 @@
from m5 import *
-from Device import PioDevice
+from Device import BasicPioDevice
-class AlphaConsole(PioDevice):
+class AlphaConsole(BasicPioDevice):
type = 'AlphaConsole'
cpu = Param.BaseCPU(Parent.any, "Processor")
disk = Param.SimpleDisk("Simple Disk")
sim_console = Param.SimConsole(Parent.any, "The Simulator Console")
- system = Param.System(Parent.any, "system object")
+ system = Param.AlphaSystem(Parent.any, "system object")
diff --git a/python/m5/objects/BadDevice.py b/python/m5/objects/BadDevice.py
index 3fba4637d..9cb9a8f03 100644
--- a/python/m5/objects/BadDevice.py
+++ b/python/m5/objects/BadDevice.py
@@ -1,6 +1,6 @@
from m5 import *
-from Device import PioDevice
+from Device import BasicPioDevice
-class BadDevice(PioDevice):
+class BadDevice(BasicPioDevice):
type = 'BadDevice'
devicename = Param.String("Name of device to error on")
diff --git a/python/m5/objects/BaseCPU.py b/python/m5/objects/BaseCPU.py
index a90203729..49cb2a8f3 100644
--- a/python/m5/objects/BaseCPU.py
+++ b/python/m5/objects/BaseCPU.py
@@ -2,13 +2,11 @@ from m5 import *
class BaseCPU(SimObject):
type = 'BaseCPU'
abstract = True
- icache = Param.BaseMem(NULL, "L1 instruction cache object")
- dcache = Param.BaseMem(NULL, "L1 data cache object")
+ mem = Param.MemObject("memory")
if build_env['FULL_SYSTEM']:
dtb = Param.AlphaDTB("Data TLB")
itb = Param.AlphaITB("Instruction TLB")
- mem = Param.FunctionalMemory("memory")
system = Param.System(Parent.any, "system object")
cpu_id = Param.Int(-1, "CPU identifier")
else:
diff --git a/python/m5/objects/Bridge.py b/python/m5/objects/Bridge.py
new file mode 100644
index 000000000..ada715ce9
--- /dev/null
+++ b/python/m5/objects/Bridge.py
@@ -0,0 +1,9 @@
+from m5 import *
+from MemObject import MemObject
+
+class Bridge(MemObject):
+ type = 'Bridge'
+ queue_size_a = Param.Int(16, "The number of requests to buffer")
+ queue_size_b = Param.Int(16, "The number of requests to buffer")
+ delay = Param.Latency('0ns', "The latency of this bridge")
+ write_ack = Param.Bool(False, "Should this bridge ack writes")
diff --git a/python/m5/objects/Bus.py b/python/m5/objects/Bus.py
index 26509d7d2..8c5397281 100644
--- a/python/m5/objects/Bus.py
+++ b/python/m5/objects/Bus.py
@@ -1,7 +1,6 @@
from m5 import *
-from BaseHier import BaseHier
+from MemObject import MemObject
-class Bus(BaseHier):
+class Bus(MemObject):
type = 'Bus'
- clock = Param.Clock("bus frequency")
- width = Param.Int("bus width in bytes")
+ bus_id = Param.Int(0, "blah")
diff --git a/python/m5/objects/Device.py b/python/m5/objects/Device.py
index d7ca014a9..2a71bbc65 100644
--- a/python/m5/objects/Device.py
+++ b/python/m5/objects/Device.py
@@ -1,35 +1,18 @@
from m5 import *
-from FunctionalMemory import FunctionalMemory
+from MemObject import MemObject
-# This device exists only because there are some devices that I don't
-# want to have a Platform parameter because it would cause a cycle in
-# the C++ that cannot be easily solved.
-#
-# The real solution to this problem is to pass the ParamXXX structure
-# to the constructor, but with the express condition that SimObject
-# parameter values are not to be available at construction time. If
-# some further configuration must be done, it must be done during the
-# initialization phase at which point all SimObject pointers will be
-# valid.
-class FooPioDevice(FunctionalMemory):
+class PioDevice(MemObject):
type = 'PioDevice'
abstract = True
- addr = Param.Addr("Device Address")
- mmu = Param.MemoryController(Parent.any, "Memory Controller")
- pio_bus = Param.Bus(NULL, "Bus to attach to for PIO")
- pio_latency = Param.Tick(1, "Programmed IO latency in bus cycles")
+ platform = Param.Platform(Parent.any, "Platform this device is part of")
+ system = Param.System(Parent.any, "System this device is part of")
-class FooDmaDevice(FooPioDevice):
- type = 'DmaDevice'
- abstract = True
- dma_bus = Param.Bus(Self.pio_bus, "Bus to attach to for DMA")
-
-class PioDevice(FooPioDevice):
- type = 'PioDevice'
+class BasicPioDevice(PioDevice):
+ type = 'BasicPioDevice'
abstract = True
- platform = Param.Platform(Parent.any, "Platform")
+ pio_addr = Param.Addr("Device Address")
+ pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
class DmaDevice(PioDevice):
type = 'DmaDevice'
abstract = True
- dma_bus = Param.Bus(Self.pio_bus, "Bus to attach to for DMA")
diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py
index 68b21b404..4286c71c8 100644
--- a/python/m5/objects/Ethernet.py
+++ b/python/m5/objects/Ethernet.py
@@ -67,15 +67,10 @@ class EtherDevBase(PciDevice):
clock = Param.Clock('0ns', "State machine processor frequency")
- physmem = Param.PhysicalMemory(Parent.any, "Physical Memory")
-
- hier = Param.HierParams(Parent.any, "Hierarchy global variables")
- payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
dma_read_delay = Param.Latency('0us', "fixed delay for dma reads")
dma_read_factor = Param.Latency('0us', "multiplier for dma reads")
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")
rx_delay = Param.Latency('1us', "Receive Delay")
tx_delay = Param.Latency('1us', "Transmit Delay")
@@ -93,6 +88,7 @@ class NSGigE(EtherDevBase):
dma_data_free = Param.Bool(False, "DMA of Data is free")
dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
+ dma_no_allocate = Param.Bool(True, "Should we allocate cache on read")
class NSGigEInt(EtherInt):
diff --git a/python/m5/objects/Ide.py b/python/m5/objects/Ide.py
index 6855ec653..2403e6d36 100644
--- a/python/m5/objects/Ide.py
+++ b/python/m5/objects/Ide.py
@@ -8,7 +8,6 @@ class IdeDisk(SimObject):
delay = Param.Latency('1us', "Fixed disk delay in microseconds")
driveID = Param.IdeID('master', "Drive ID")
image = Param.DiskImage("Disk image")
- physmem = Param.PhysicalMemory(Parent.any, "Physical memory")
class IdeController(PciDevice):
type = 'IdeController'
diff --git a/python/m5/objects/MemObject.py b/python/m5/objects/MemObject.py
new file mode 100644
index 000000000..4d68243e6
--- /dev/null
+++ b/python/m5/objects/MemObject.py
@@ -0,0 +1,5 @@
+from m5 import *
+
+class MemObject(SimObject):
+ type = 'MemObject'
+ abstract = True
diff --git a/python/m5/objects/Pci.py b/python/m5/objects/Pci.py
index 4124d0b92..85cefcd44 100644
--- a/python/m5/objects/Pci.py
+++ b/python/m5/objects/Pci.py
@@ -1,5 +1,5 @@
from m5 import *
-from Device import FooPioDevice, DmaDevice
+from Device import BasicPioDevice, DmaDevice
class PciConfigData(SimObject):
type = 'PciConfigData'
@@ -38,16 +38,16 @@ class PciConfigData(SimObject):
MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
-class PciConfigAll(FooPioDevice):
+class PciConfigAll(BasicPioDevice):
type = 'PciConfigAll'
class PciDevice(DmaDevice):
type = 'PciDevice'
abstract = True
- addr = 0xffffffffL
pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number")
pci_func = Param.Int("PCI function code")
+ pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
configdata = Param.PciConfigData(Parent.any, "PCI Config data")
configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
diff --git a/python/m5/objects/PhysicalMemory.py b/python/m5/objects/PhysicalMemory.py
index f50937ee6..e59e94e9b 100644
--- a/python/m5/objects/PhysicalMemory.py
+++ b/python/m5/objects/PhysicalMemory.py
@@ -1,8 +1,8 @@
from m5 import *
-from FunctionalMemory import FunctionalMemory
+from MemObject import *
-class PhysicalMemory(FunctionalMemory):
+class PhysicalMemory(MemObject):
type = 'PhysicalMemory'
range = Param.AddrRange("Device Address")
file = Param.String('', "memory mapped file")
- mmu = Param.MemoryController(Parent.any, "Memory Controller")
+ latency = Param.Latency('10ns', "latency of an access")
diff --git a/python/m5/objects/Process.py b/python/m5/objects/Process.py
index b4ccc1bec..60b00229e 100644
--- a/python/m5/objects/Process.py
+++ b/python/m5/objects/Process.py
@@ -3,6 +3,7 @@ class Process(SimObject):
type = 'Process'
abstract = True
output = Param.String('cout', 'filename for stdout/stderr')
+ system = Param.System(Parent.any, "system process will run on")
class LiveProcess(Process):
type = 'LiveProcess'
@@ -11,6 +12,15 @@ class LiveProcess(Process):
env = VectorParam.String('', "environment settings")
input = Param.String('cin', "filename for stdin")
+class AlphaLiveProcess(LiveProcess):
+ type = 'AlphaLiveProcess'
+
+class SparcLiveProcess(LiveProcess):
+ type = 'SparcLiveProcess'
+
+class MipsLiveProcess(LiveProcess):
+ type = 'MipsLiveProcess'
+
class EioProcess(Process):
type = 'EioProcess'
chkpt = Param.String('', "EIO checkpoint file name (optional)")
diff --git a/python/m5/objects/Root.py b/python/m5/objects/Root.py
index 23b13fc67..f51516098 100644
--- a/python/m5/objects/Root.py
+++ b/python/m5/objects/Root.py
@@ -1,5 +1,4 @@
from m5 import *
-from HierParams import HierParams
from Serialize import Serialize
from Statistics import Statistics
from Trace import Trace
@@ -13,12 +12,9 @@ class Root(SimObject):
"print a progress message every n ticks (0 = never)")
output_file = Param.String('cout', "file to dump simulator output to")
checkpoint = Param.String('', "checkpoint file to load")
-# hier = Param.HierParams(HierParams(do_data = False, do_events = True),
-# "shared memory hierarchy parameters")
# stats = Param.Statistics(Statistics(), "statistics object")
# trace = Param.Trace(Trace(), "trace object")
# serialize = Param.Serialize(Serialize(), "checkpoint generation options")
- hier = HierParams(do_data = False, do_events = True)
stats = Statistics()
trace = Trace()
exetrace = ExecutionTrace()
diff --git a/python/m5/objects/SimpleDisk.py b/python/m5/objects/SimpleDisk.py
index 48448e6e5..e34155ace 100644
--- a/python/m5/objects/SimpleDisk.py
+++ b/python/m5/objects/SimpleDisk.py
@@ -2,4 +2,4 @@ from m5 import *
class SimpleDisk(SimObject):
type = 'SimpleDisk'
disk = Param.DiskImage("Disk Image")
- physmem = Param.PhysicalMemory(Parent.any, "Physical Memory")
+ system = Param.System(Parent.any, "Sysetm Pointer")
diff --git a/python/m5/objects/System.py b/python/m5/objects/System.py
index 5925cadf5..622b5a870 100644
--- a/python/m5/objects/System.py
+++ b/python/m5/objects/System.py
@@ -2,20 +2,20 @@ 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")
+ 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")
+ boot_osflags = Param.String("a", "boot flags to pass to the kernel")
+ kernel = Param.String("file that contains the kernel code")
+ readfile = Param.String("", "file to read startup script from")
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/python/m5/objects/Tsunami.py b/python/m5/objects/Tsunami.py
index 5425f421f..27ea0bce8 100644
--- a/python/m5/objects/Tsunami.py
+++ b/python/m5/objects/Tsunami.py
@@ -1,27 +1,27 @@
from m5 import *
-from Device import FooPioDevice
+from Device import BasicPioDevice
from Platform import Platform
class Tsunami(Platform):
type = 'Tsunami'
- pciconfig = Param.PciConfigAll("PCI configuration")
+# pciconfig = Param.PciConfigAll("PCI configuration")
system = Param.System(Parent.any, "system")
-class TsunamiCChip(FooPioDevice):
+class TsunamiCChip(BasicPioDevice):
type = 'TsunamiCChip'
tsunami = Param.Tsunami(Parent.any, "Tsunami")
-class IsaFake(FooPioDevice):
+class IsaFake(BasicPioDevice):
type = 'IsaFake'
- size = Param.Addr("Size of address range")
+ pio_size = Param.Addr(0x8, "Size of address range")
-class TsunamiIO(FooPioDevice):
+class TsunamiIO(BasicPioDevice):
type = 'TsunamiIO'
time = Param.UInt64(1136073600,
"System time to use (0 for actual time, default is 1/1/06)")
tsunami = Param.Tsunami(Parent.any, "Tsunami")
frequency = Param.Frequency('1024Hz', "frequency of interrupts")
-class TsunamiPChip(FooPioDevice):
+class TsunamiPChip(BasicPioDevice):
type = 'TsunamiPChip'
tsunami = Param.Tsunami(Parent.any, "Tsunami")
diff --git a/python/m5/objects/Uart.py b/python/m5/objects/Uart.py
index 6eda5cdb3..54754aeb9 100644
--- a/python/m5/objects/Uart.py
+++ b/python/m5/objects/Uart.py
@@ -1,11 +1,10 @@
from m5 import *
-from Device import PioDevice
+from Device import BasicPioDevice
-class Uart(PioDevice):
+class Uart(BasicPioDevice):
type = 'Uart'
abstract = True
- console = Param.SimConsole(Parent.any, "The console")
- size = Param.Addr(0x8, "Device size")
+ sim_console = Param.SimConsole(Parent.any, "The console")
class Uart8250(Uart):
type = 'Uart8250'
diff --git a/sim/byteswap.hh b/sim/byteswap.hh
index c5d8801ab..a8c5da9d7 100644
--- a/sim/byteswap.hh
+++ b/sim/byteswap.hh
@@ -38,6 +38,10 @@
// This lets us figure out what the byte order of the host system is
#if defined(linux)
#include <endian.h>
+// If this is a linux system, lets used the optimized definitions if they exist.
+// If one doesn't exist, we pretty much get what is listed below, so it all
+// works out
+#include <byteswap.h>
#else
#include <machine/endian.h>
#endif
@@ -47,6 +51,9 @@
static inline uint64_t
swap_byte64(uint64_t x)
{
+#if defined(linux)
+ return bswap_64(x);
+#else
return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
((uint64_t)(x) & 0xff00ULL) << 40 |
((uint64_t)(x) & 0xff0000ULL) << 24 |
@@ -55,22 +62,30 @@ swap_byte64(uint64_t x)
((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
+#endif
}
static inline uint32_t
swap_byte32(uint32_t x)
{
+#if defined(linux)
+ return bswap_32(x);
+#else
return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
((uint32_t)(x) & 0xff000000) >> 24);
-
+#endif
}
static inline uint16_t
swap_byte16(uint16_t x)
{
+#if defined(linux)
+ return bswap_16(x);
+#else
return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
((uint16_t)(x) & 0xff00) >> 8);
+#endif
}
//This lets the compiler figure out how to call the swap_byte functions above
@@ -79,7 +94,9 @@ 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__)
+//This is to prevent the following two functions from compiling on
+//64bit machines. It won't detect everything, so it should be changed.
+#ifndef __x86_64__
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);}
diff --git a/sim/faults.cc b/sim/faults.cc
index 701384989..f7e9a0691 100644
--- a/sim/faults.cc
+++ b/sim/faults.cc
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "base/misc.hh"
#include "sim/faults.hh"
#include "cpu/exec_context.hh"
#include "cpu/base.hh"
diff --git a/sim/host.hh b/sim/host.hh
index f7e64f23c..48c977331 100644
--- a/sim/host.hh
+++ b/sim/host.hh
@@ -62,4 +62,6 @@ typedef int64_t Tick;
*/
typedef uint64_t Addr;
+const Addr MaxAddr = (Addr)-1;
+
#endif // __HOST_H__
diff --git a/sim/main.cc b/sim/main.cc
index 6f6143506..aecc171ed 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -355,6 +355,10 @@ main(int argc, char **argv)
echoCommandLine(argc, argv, *outputStream);
ParamContext::showAllContexts(*configStream);
+ // Any objects that can't connect themselves until after construction should
+ // do so now
+ SimObject::connectAll();
+
// Do a second pass to finish initializing the sim objects
SimObject::initAll();
diff --git a/sim/process.cc b/sim/process.cc
index a84a4f7ba..d88716f1e 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -37,18 +37,15 @@
#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"
-#include "encumbered/eio/eio.hh"
-#include "encumbered/mem/functional/main.hh"
+#include "mem/page_table.hh"
+#include "mem/physical.hh"
+#include "mem/translating_port.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/stats.hh"
#include "sim/syscall_emul.hh"
-
-#include "arch/process.hh"
+#include "sim/system.hh"
using namespace std;
using namespace TheISA;
@@ -66,20 +63,12 @@ using namespace TheISA;
int num_processes = 0;
Process::Process(const string &nm,
+ System *_system,
int stdin_fd, // initial I/O descriptors
int stdout_fd,
int stderr_fd)
- : SimObject(nm)
+ : SimObject(nm), system(_system)
{
- // allocate memory space
- memory = new MainMemory(nm + ".MainMem");
-
- // allocate initial register file
- init_regs = new RegFile;
- memset(init_regs, 0, sizeof(RegFile));
-
- cpuXC = new CPUExecContext(init_regs);
-
// initialize first 3 fds (stdin, stdout, stderr)
fd_map[STDIN_FILENO] = stdin_fd;
fd_map[STDOUT_FILENO] = stdout_fd;
@@ -92,9 +81,11 @@ Process::Process(const string &nm,
mmap_start = mmap_end = 0;
nxm_start = nxm_end = 0;
+ pTable = new PageTable(system);
// other parameters will be initialized when the program is loaded
}
+
void
Process::regStats()
{
@@ -146,13 +137,7 @@ Process::registerExecContext(ExecContext *xc)
int myIndex = execContexts.size();
execContexts.push_back(xc);
- if (myIndex == 0) {
- // copy process's initial regs struct
- // Hack for now to copy init regs
- xc->copyArchRegs(cpuXC->getProxy());
- }
-
- // return CPU number to caller and increment available CPU count
+ // return CPU number to caller
return myIndex;
}
@@ -160,13 +145,19 @@ void
Process::startup()
{
if (execContexts.empty())
- return;
+ fatal("Process %s is not associated with any CPUs!\n", name());
// first exec context for this process... initialize & enable
ExecContext *xc = execContexts[0];
// mark this context as active so it will start ticking.
xc->activate(0);
+
+ Port *mem_port;
+ mem_port = system->physmem->getPort("functional");
+ initVirtMem = new TranslatingPort(pTable, true);
+ mem_port->setPeer(initVirtMem);
+ initVirtMem->setPeer(mem_port);
}
void
@@ -249,40 +240,33 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
////////////////////////////////////////////////////////////////////////
-static void
+void
copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
- FunctionalMemory *memory)
+ TranslatingPort* memPort)
{
Addr data_ptr_swap;
for (int i = 0; i < strings.size(); ++i) {
data_ptr_swap = htog(data_ptr);
- memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr));
- memory->writeString(data_ptr, strings[i].c_str());
+ memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr));
+ memPort->writeString(data_ptr, strings[i].c_str());
array_ptr += sizeof(Addr);
data_ptr += strings[i].size() + 1;
}
// add NULL terminator
data_ptr = 0;
- memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
+
+ memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr));
}
-LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
+LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile,
+ System *_system,
int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
- : Process(nm, stdin_fd, stdout_fd, stderr_fd)
+ vector<string> &_argv, vector<string> &_envp)
+ : Process(nm, _system, stdin_fd, stdout_fd, stderr_fd),
+ objFile(_objFile), argv(_argv), envp(_envp)
{
prog_fname = argv[0];
- prog_entry = objFile->entryPoint();
- text_base = objFile->textBase();
- text_size = objFile->textSize();
- data_base = objFile->dataBase();
- data_size = objFile->dataSize() + objFile->bssSize();
- brk_point = roundUp(data_base + data_size, VMPageSize);
-
- // load object file into target memory
- objFile->loadSections(memory);
-
// load up symbols, if any... these may be used for debugging or
// profiling.
if (!debugSymbolTable) {
@@ -294,21 +278,19 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
debugSymbolTable = NULL;
}
}
+}
- // Set up stack. On Alpha, stack goes below text section. This
- // code should get moved to some architecture-specific spot.
- stack_base = text_base - (409600+4096);
-
- // Set up region for mmaps. Tru64 seems to start just above 0 and
- // grow up from there.
- mmap_start = mmap_end = 0x10000;
+void
+LiveProcess::argsInit(int intSize, int pageSize)
+{
+ Process::startup();
- // Set pointer for next thread stack. Reserve 8M for main stack.
- next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+ // load object file into target memory
+ objFile->loadSections(initVirtMem);
// Calculate how much space we need for arg & env arrays.
- int argv_array_size = sizeof(Addr) * (argv.size() + 1);
- int envp_array_size = sizeof(Addr) * (envp.size() + 1);
+ int argv_array_size = intSize * (argv.size() + 1);
+ int envp_array_size = intSize * (envp.size() + 1);
int arg_data_size = 0;
for (int i = 0; i < argv.size(); ++i) {
arg_data_size += argv[i].size() + 1;
@@ -327,38 +309,49 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
// set bottom of stack
stack_min = stack_base - space_needed;
// align it
- stack_min &= ~7;
+ stack_min &= ~(intSize-1);
stack_size = stack_base - stack_min;
+ // map memory
+ pTable->allocate(roundDown(stack_min, pageSize),
+ roundUp(stack_size, pageSize));
// map out initial stack contents
- Addr argv_array_base = stack_min + sizeof(uint64_t); // room for argc
+ Addr argv_array_base = stack_min + intSize; // room for argc
Addr envp_array_base = argv_array_base + argv_array_size;
Addr arg_data_base = envp_array_base + envp_array_size;
Addr env_data_base = arg_data_base + arg_data_size;
// write contents to stack
uint64_t argc = argv.size();
- argc = htog(argc);
- memory->access(Write, stack_min, &argc, sizeof(uint64_t));
-
- copyStringArray(argv, argv_array_base, arg_data_base, memory);
- copyStringArray(envp, envp_array_base, env_data_base, memory);
-
- cpuXC->setIntReg(ArgumentReg0, argc);
- cpuXC->setIntReg(ArgumentReg1, argv_array_base);
- cpuXC->setIntReg(StackPointerReg, stack_min);
- cpuXC->setIntReg(GlobalPointerReg, objFile->globalPointer());
- cpuXC->setPC(prog_entry);
- cpuXC->setNextPC(prog_entry + sizeof(MachInst));
+ if (intSize == 8)
+ argc = htog((uint64_t)argc);
+ else if (intSize == 4)
+ argc = htog((uint32_t)argc);
+ else
+ panic("Unknown int size");
+
+ initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize);
+
+ copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
+ copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
+
+ execContexts[0]->setIntReg(ArgumentReg0, argc);
+ execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
+ execContexts[0]->setIntReg(StackPointerReg, stack_min);
+
+ Addr prog_entry = objFile->entryPoint();
+ execContexts[0]->setPC(prog_entry);
+ execContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+ execContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+
+ num_processes++;
}
void
-LiveProcess::syscall(ExecContext *xc)
+LiveProcess::syscall(int64_t callnum, ExecContext *xc)
{
num_syscalls++;
- int64_t callnum = xc->readIntReg(SyscallNumReg);
-
SyscallDesc *desc = getDesc(callnum);
if (desc == NULL)
fatal("Syscall %d out of range", callnum);
@@ -366,81 +359,4 @@ LiveProcess::syscall(ExecContext *xc)
desc->doSyscall(callnum, this, xc);
}
-LiveProcess *
-LiveProcess::create(const string &nm,
- int stdin_fd, int stdout_fd, int stderr_fd,
- string executable,
- vector<string> &argv, vector<string> &envp)
-{
- LiveProcess *process = NULL;
- ObjectFile *objFile = createObjectFile(executable);
- if (objFile == NULL) {
- fatal("Can't load object file %s", executable);
- }
-
- // set up syscall emulation pointer for the current ISA
- process = createProcess(nm, objFile,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
-
- delete objFile;
-
- if (process == NULL)
- fatal("Unknown error creating process object.");
-
- return process;
-}
-
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
-
- VectorParam<string> cmd;
- Param<string> executable;
- Param<string> input;
- Param<string> output;
- VectorParam<string> env;
-
-END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess)
-
- INIT_PARAM(cmd, "command line (executable plus arguments)"),
- INIT_PARAM(executable, "executable (overrides cmd[0] if set)"),
- INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
- INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
- INIT_PARAM(env, "environment settings")
-
-END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
-
-
-CREATE_SIM_OBJECT(LiveProcess)
-{
- string in = input;
- string out = output;
-
- // initialize file descriptors to default: same as simulator
- int stdin_fd, stdout_fd, stderr_fd;
-
- if (in == "stdin" || in == "cin")
- stdin_fd = STDIN_FILENO;
- else
- stdin_fd = Process::openInputFile(input);
-
- if (out == "stdout" || out == "cout")
- stdout_fd = STDOUT_FILENO;
- else if (out == "stderr" || out == "cerr")
- stdout_fd = STDERR_FILENO;
- else
- stdout_fd = Process::openOutputFile(out);
-
- stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
-
- return LiveProcess::create(getInstanceName(),
- stdin_fd, stdout_fd, stderr_fd,
- (string)executable == "" ? cmd[0] : executable,
- cmd, env);
-}
-
-REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)
+DEFINE_SIM_OBJECT_CLASS_NAME("LiveProcess", LiveProcess);
diff --git a/sim/process.hh b/sim/process.hh
index 3a48f128c..807bf330f 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -40,23 +40,28 @@
#include <vector>
-#include "arch/isa_traits.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
#include "base/statistics.hh"
-#include "base/trace.hh"
+#include "sim/sim_object.hh"
class CPUExecContext;
class ExecContext;
-class FunctionalMemory;
class SyscallDesc;
+class PageTable;
+class TranslatingPort;
+class System;
+
+void
+copyStringArray(std::vector<std::string> &strings, Addr array_ptr,
+ Addr data_ptr, TranslatingPort* memPort);
+
class Process : public SimObject
{
- protected:
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MachInst MachInst;
public:
+ /// Pointer to object representing the system this process is
+ /// running on.
+ System *system;
+
// have we initialized an execution context from this process? If
// yes, subsequent contexts are assumed to be for dynamically
// created threads and are not initialized.
@@ -76,22 +81,12 @@ class Process : public SimObject
WaitRec(Addr chan, ExecContext *ctx)
: waitChan(chan), waitingContext(ctx)
- {
- }
+ { }
};
// list of all blocked contexts
std::list<WaitRec> waitList;
- RegFile *init_regs; // initial register contents
- CPUExecContext *cpuXC; // XC to hold the init_regs
-
- Addr text_base; // text (code) segment base
- unsigned text_size; // text (code) size in bytes
-
- Addr data_base; // initialized data segment base
- unsigned data_size; // initialized data + bss size in bytes
-
Addr brk_point; // top of the data segment
Addr stack_base; // stack segment base (highest address)
@@ -110,7 +105,6 @@ class Process : public SimObject
Addr nxm_end;
std::string prog_fname; // file name
- Addr prog_entry; // entry point (initial PC)
Stats::Scalar<> num_syscalls; // number of syscalls executed
@@ -118,6 +112,7 @@ class Process : public SimObject
protected:
// constructor
Process(const std::string &nm,
+ System *_system,
int stdin_fd, // initial I/O descriptors
int stdout_fd,
int stderr_fd);
@@ -126,7 +121,11 @@ class Process : public SimObject
virtual void startup();
protected:
- FunctionalMemory *memory;
+ /// Memory object for initialization (image loading)
+ TranslatingPort *initVirtMem;
+
+ public:
+ PageTable *pTable;
private:
// file descriptor remapping support
@@ -160,29 +159,7 @@ class Process : public SimObject
// look up simulator fd for given target fd
int sim_fd(int tgt_fd);
- // is this a valid instruction fetch address?
- bool validInstAddr(Addr addr)
- {
- return (text_base <= addr &&
- addr < text_base + text_size &&
- !(addr & (sizeof(MachInst)-1)));
- }
-
- // is this a valid address? (used to filter data fetches)
- // note that we just assume stack size <= 16MB
- // this may be alpha-specific
- bool validDataAddr(Addr addr)
- {
- return ((data_base <= addr && addr < brk_point) ||
- (next_thread_stack_base <= addr && addr < stack_base) ||
- (text_base <= addr && addr < (text_base + text_size)) ||
- (mmap_start <= addr && addr < mmap_end) ||
- (nxm_start <= addr && addr < nxm_end));
- }
-
- virtual void syscall(ExecContext *xc) = 0;
-
- virtual FunctionalMemory *getMemory() { return memory; }
+ virtual void syscall(int64_t callnum, ExecContext *xc) = 0;
};
//
@@ -192,25 +169,21 @@ class ObjectFile;
class LiveProcess : public Process
{
protected:
+ ObjectFile *objFile;
+ std::vector<std::string> argv;
+ std::vector<std::string> envp;
+
LiveProcess(const std::string &nm, ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
- public:
- // this function is used to create the LiveProcess object, since
- // we can't tell which subclass of LiveProcess to use until we
- // open and look at the object file.
- static LiveProcess *create(const std::string &nm,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::string executable,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp);
-
- virtual void syscall(ExecContext *xc);
+ virtual void argsInit(int intSize, int pageSize);
- virtual SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); }
+ public:
+ virtual void syscall(int64_t callnum, ExecContext *xc);
+ virtual SyscallDesc* getDesc(int callnum) = 0;
};
diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc
index e475006e7..3cdc05e78 100644
--- a/sim/pseudo_inst.cc
+++ b/sim/pseudo_inst.cc
@@ -175,7 +175,7 @@ namespace AlphaPseudo
addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
{
char symb[100];
- CopyString(xc, symb, symbolAddr, 100);
+ CopyStringOut(xc, symb, symbolAddr, 100);
std::string symbol(symb);
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
diff --git a/sim/sim_object.cc b/sim/sim_object.cc
index f34e17fe6..17d58ba4f 100644
--- a/sim/sim_object.cc
+++ b/sim/sim_object.cc
@@ -34,6 +34,7 @@
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/stats/events.hh"
+#include "base/serializer.hh"
#include "sim/configfile.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
@@ -88,6 +89,11 @@ SimObject::SimObject(const string &_name)
}
void
+SimObject::connect()
+{
+}
+
+void
SimObject::init()
{
}
@@ -151,6 +157,21 @@ SimObject::regAllStats()
}
//
+// static function: call connect() on all SimObjects.
+//
+void
+SimObject::connectAll()
+{
+ SimObjectList::iterator i = simObjectList.begin();
+ SimObjectList::iterator end = simObjectList.end();
+
+ for (; i != end; ++i) {
+ SimObject *obj = *i;
+ obj->connect();
+ }
+}
+
+//
// static function: call init() on all SimObjects.
//
void
@@ -228,4 +249,10 @@ SimObject::recordEvent(const std::string &stat)
Stats::recordEvent(stat);
}
+void
+SimObject::drain(Serializer *serializer)
+{
+ serializer->signalDrained();
+}
+
DEFINE_SIM_OBJECT_CLASS_NAME("SimObject", SimObject)
diff --git a/sim/sim_object.hh b/sim/sim_object.hh
index 59d9daf45..76aba7ea1 100644
--- a/sim/sim_object.hh
+++ b/sim/sim_object.hh
@@ -41,6 +41,8 @@
#include "sim/serialize.hh"
#include "sim/startup.hh"
+class Serializer;
+
/*
* Abstract superclass for simulation objects. Represents things that
* correspond to physical components and can be specified via the
@@ -78,7 +80,9 @@ class SimObject : public Serializable, protected StartupCallback
// initialization pass of all objects.
// Gets invoked after construction, before unserialize.
virtual void init();
+ virtual void connect();
static void initAll();
+ static void connectAll();
// register statistics for this object
virtual void regStats();
@@ -94,6 +98,13 @@ class SimObject : public Serializable, protected StartupCallback
// static: call nameOut() & serialize() on all SimObjects
static void serializeAll(std::ostream &);
+ // Methods to drain objects in order to take checkpoints
+ // Or switch from timing -> atomic memory model
+ virtual void drain(Serializer *serializer);
+ virtual void resume() { return;} ;
+ virtual void serializationComplete()
+ { assert(0 && "Unimplemented"); };
+
#ifdef DEBUG
public:
bool doDebugBreak;
diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc
index 00168b025..ed0da628e 100644
--- a/sim/syscall_emul.cc
+++ b/sim/syscall_emul.cc
@@ -33,9 +33,11 @@
#include <iostream>
#include "sim/syscall_emul.hh"
+#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "cpu/exec_context.hh"
#include "cpu/base.hh"
+#include "mem/page_table.hh"
#include "sim/process.hh"
#include "sim/sim_events.hh"
@@ -46,13 +48,15 @@ using namespace TheISA;
void
SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
{
- DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
- xc->getCpuPtr()->name(), name);
+ DPRINTFR(SyscallVerbose, "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n",
+ curTick,xc->getCpuPtr()->name(), name,
+ xc->getSyscallArg(0),xc->getSyscallArg(1),
+ xc->getSyscallArg(2),xc->getSyscallArg(3));
SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
- DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
- xc->getCpuPtr()->name(), name, retval.value());
+ DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n",
+ curTick,xc->getCpuPtr()->name(), name, retval.value());
if (!(flags & SyscallDesc::SuppressReturnValue))
xc->setSyscallReturn(retval);
@@ -64,6 +68,8 @@ unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
+
+ return 1;
}
@@ -82,7 +88,7 @@ SyscallReturn
exitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
- new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
+ new SimExitEvent("target called exit()", xc->getSyscallArg(0) & 0xff);
return 1;
}
@@ -98,11 +104,18 @@ getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
SyscallReturn
obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
+ Addr junk;
+
// change brk addr to first arg
Addr new_brk = xc->getSyscallArg(0);
- if (new_brk != 0)
- {
- p->brk_point = xc->getSyscallArg(0);
+ if (new_brk != 0) {
+ for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point,
+ VMPageSize); !gen.done(); gen.next()) {
+ if (!p->pTable->translate(gen.addr(), junk))
+ p->pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ }
+ p->brk_point = new_brk;
}
DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
return p->brk_point;
@@ -130,7 +143,7 @@ readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
if (bytes_read != -1)
- bufArg.copyOut(xc->getMemPtr());
+ bufArg.copyOut(xc->getMemPort());
return bytes_read;
}
@@ -142,7 +155,7 @@ writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
int nbytes = xc->getSyscallArg(2);
BufferArg bufArg(xc->getSyscallArg(1), nbytes);
- bufArg.copyIn(xc->getMemPtr());
+ bufArg.copyIn(xc->getMemPort());
int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
@@ -183,7 +196,7 @@ gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
strncpy((char *)name.bufferPtr(), hostname, name_len);
- name.copyOut(xc->getMemPtr());
+ name.copyOut(xc->getMemPort());
return 0;
}
@@ -193,7 +206,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
return (TheISA::IntReg)-EFAULT;
int result = unlink(path.c_str());
@@ -205,12 +218,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string old_name;
- if (xc->getMemPtr()->readString(old_name, xc->getSyscallArg(0)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(old_name, xc->getSyscallArg(0)))
return -EFAULT;
string new_name;
- if (xc->getMemPtr()->readString(new_name, xc->getSyscallArg(1)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(new_name, xc->getSyscallArg(1)))
return -EFAULT;
int64_t result = rename(old_name.c_str(), new_name.c_str());
@@ -222,7 +235,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
return -EFAULT;
off_t length = xc->getSyscallArg(1);
@@ -250,7 +263,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
return -EFAULT;
/* XXX endianess */
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
index 35129bcb4..00f016410 100644
--- a/sim/syscall_emul.hh
+++ b/sim/syscall_emul.hh
@@ -45,12 +45,15 @@
#endif
#include <sys/uio.h>
-#include "base/intmath.hh" // for RoundUp
-#include "mem/functional/functional.hh"
#include "arch/isa_traits.hh" // for Addr
-
+#include "base/chunk_generator.hh"
+#include "base/intmath.hh" // for RoundUp
+#include "base/misc.hh"
#include "base/trace.hh"
+#include "cpu/base.hh"
#include "cpu/exec_context.hh"
+#include "mem/translating_port.hh"
+#include "mem/page_table.hh"
#include "sim/process.hh"
///
@@ -106,18 +109,18 @@ class BaseBufferArg {
//
// copy data into simulator space (read from target memory)
//
- virtual bool copyIn(FunctionalMemory *mem)
+ virtual bool copyIn(TranslatingPort *memport)
{
- mem->access(Read, addr, bufPtr, size);
+ memport->readBlob(addr, bufPtr, size);
return true; // no EFAULT detection for now
}
//
// copy data out of simulator space (write to target memory)
//
- virtual bool copyOut(FunctionalMemory *mem)
+ virtual bool copyOut(TranslatingPort *memport)
{
- mem->access(Write, addr, bufPtr, size);
+ memport->writeBlob(addr, bufPtr, size);
return true; // no EFAULT detection for now
}
@@ -369,7 +372,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
return -EFAULT;
if (path == "/dev/sysdev0") {
@@ -416,7 +419,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
return -EFAULT;
uint32_t mode = xc->getSyscallArg(1);
@@ -469,8 +472,8 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
struct stat hostBuf;
int result = stat(path.c_str(), &hostBuf);
@@ -478,7 +481,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -507,7 +510,7 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStat64Buf(xc->getMemPtr(), fd, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -521,8 +524,8 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
struct stat hostBuf;
int result = lstat(path.c_str(), &hostBuf);
@@ -530,7 +533,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -543,8 +546,8 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
#if BSD_HOST
struct stat hostBuf;
@@ -557,7 +560,7 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStat64Buf(xc->getMemPtr(), -1, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -581,7 +584,8 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+
return 0;
}
@@ -594,8 +598,8 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
struct statfs hostBuf;
int result = statfs(path.c_str(), &hostBuf);
@@ -603,7 +607,7 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -626,7 +630,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -644,18 +648,20 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
return -EBADF;
}
+ TranslatingPort *p = xc->getMemPort();
uint64_t tiov_base = xc->getSyscallArg(1);
size_t count = xc->getSyscallArg(2);
struct iovec hiov[count];
for (int i = 0; i < count; ++i)
{
typename OS::tgt_iovec tiov;
- xc->getMemPtr()->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec),
- &tiov, sizeof(typename OS::tgt_iovec));
+
+ p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
+ (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
hiov[i].iov_len = gtoh(tiov.iov_len);
hiov[i].iov_base = new char [hiov[i].iov_len];
- xc->getMemPtr()->access(Read, gtoh(tiov.iov_base),
- hiov[i].iov_base, hiov[i].iov_len);
+ p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
+ hiov[i].iov_len);
}
int result = writev(process->sim_fd(fd), hiov, count);
@@ -695,16 +701,24 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
// int fd = p->sim_fd(xc->getSyscallArg(4));
// int offset = xc->getSyscallArg(5);
- if (start == 0) {
- // user didn't give an address... pick one from our "mmap region"
- start = p->mmap_end;
- 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);
- }
+ if ((start % TheISA::VMPageSize) != 0 ||
+ (length % TheISA::VMPageSize) != 0) {
+ warn("mmap failing: arguments not page-aligned: "
+ "start 0x%x length 0x%x",
+ start, length);
+ return -EINVAL;
+ }
+
+ if (start != 0) {
+ warn("mmap: ignoring suggested map address 0x%x, using 0x%x",
+ start, p->mmap_end);
}
+ // pick next address from our "mmap region"
+ start = p->mmap_end;
+ p->pTable->allocate(start, length);
+ p->mmap_end += length;
+
if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
warn("allowing mmap of file @ fd %d. "
"This will break if not /dev/zero.", xc->getSyscallArg(4));
@@ -737,7 +751,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
break;
}
- rlp.copyOut(xc->getMemPtr());
+ rlp.copyOut(xc->getMemPort());
return 0;
}
@@ -754,7 +768,7 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
tp->tv_sec = htog(tp->tv_sec);
tp->tv_usec = htog(tp->tv_usec);
- tp.copyOut(xc->getMemPtr());
+ tp.copyOut(xc->getMemPort());
return 0;
}
@@ -768,11 +782,11 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
- tp.copyIn(xc->getMemPtr());
+ tp.copyIn(xc->getMemPort());
struct timeval hostTimeval[2];
for (int i = 0; i < 2; ++i)
@@ -824,9 +838,12 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
rup->ru_nvcsw = 0;
rup->ru_nivcsw = 0;
- rup.copyOut(xc->getMemPtr());
+ rup.copyOut(xc->getMemPort());
return 0;
}
+
+
+
#endif // __SIM_SYSCALL_EMUL_HH__
diff --git a/sim/system.cc b/sim/system.cc
index 8820922c1..ca9d68d77 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -1,16 +1,18 @@
+#include "arch/isa_traits.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
-#include "base/remote_gdb.hh"
+#include "base/trace.hh"
#include "cpu/exec_context.hh"
-#include "kern/kernel_stats.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "arch/vtophys.hh"
+#include "mem/mem_object.hh"
+#include "mem/physical.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
+#include "arch/vtophys.hh"
+#include "base/remote_gdb.hh"
+#include "kern/kernel_stats.hh"
+#endif
using namespace std;
using namespace TheISA;
@@ -20,15 +22,35 @@ vector<System *> System::systemList;
int System::numSystemsRunning = 0;
System::System(Params *p)
- : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem),
- init_param(p->init_param), numcpus(0), _params(p)
+ : SimObject(p->name), physmem(p->physmem), numcpus(0),
+#if FULL_SYSTEM
+ init_param(p->init_param),
+#else
+ page_ptr(0),
+#endif
+ _params(p)
{
// add self to global system list
systemList.push_back(this);
+#if FULL_SYSTEM
kernelSymtab = new SymbolTable;
debugSymbolTable = new SymbolTable;
+
+ /**
+ * Get a functional port to memory
+ */
+ Port *mem_port;
+ mem_port = physmem->getPort("functional");
+ functionalPort.setPeer(mem_port);
+ mem_port->setPeer(&functionalPort);
+
+ mem_port = physmem->getPort("functional");
+ virtPort.setPeer(mem_port);
+ mem_port->setPeer(&virtPort);
+
+
/**
* Load the kernel code into memory
*/
@@ -38,7 +60,7 @@ System::System(Params *p)
fatal("Could not load kernel file %s", params()->kernel_path);
// Load program sections into memory
- kernel->loadSections(physmem, true);
+ kernel->loadSections(&functionalPort, LoadAddrMask);
// setup entry points
kernelStart = kernel->textBase();
@@ -63,25 +85,33 @@ System::System(Params *p)
DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
DPRINTF(Loader, "Kernel loaded...\n");
+ kernelBinning = new Kernel::Binning(this);
+#endif // FULL_SYSTEM
+
// increment the number of running systms
numSystemsRunning++;
-
- kernelBinning = new Kernel::Binning(this);
}
System::~System()
{
+#if FULL_SYSTEM
delete kernelSymtab;
delete kernel;
delete kernelBinning;
+#else
+ panic("System::fixFuncEventAddr needs to be rewritten "
+ "to work with syscall emulation");
+#endif // FULL_SYSTEM}
}
-
+#if FULL_SYSTEM
int rgdb_wait = -1;
+#endif // FULL_SYSTEM
+
int
System::registerExecContext(ExecContext *xc, int id)
{
@@ -101,6 +131,7 @@ System::registerExecContext(ExecContext *xc, int id)
execContexts[id] = xc;
numcpus++;
+#if FULL_SYSTEM
RemoteGDB *rgdb = new RemoteGDB(this, xc);
GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
gdbl->listen();
@@ -116,6 +147,7 @@ System::registerExecContext(ExecContext *xc, int id)
}
remoteGDB[id] = rgdb;
+#endif // FULL_SYSTEM
return id;
}
@@ -137,30 +169,48 @@ System::replaceExecContext(ExecContext *xc, int id)
}
execContexts[id] = xc;
+#if FULL_SYSTEM
remoteGDB[id]->replaceExecContext(xc);
+#endif // FULL_SYSTEM
+}
+
+#if !FULL_SYSTEM
+Addr
+System::new_page()
+{
+ Addr return_addr = page_ptr << LogVMPageSize;
+ ++page_ptr;
+ return return_addr;
}
+#endif
void
System::regStats()
{
+#if FULL_SYSTEM
kernelBinning->regStats(name() + ".kern");
+#endif // FULL_SYSTEM
}
void
System::serialize(ostream &os)
{
+#if FULL_SYSTEM
kernelBinning->serialize(os);
kernelSymtab->serialize("kernel_symtab", os);
+#endif // FULL_SYSTEM
}
void
System::unserialize(Checkpoint *cp, const string &section)
{
+#if FULL_SYSTEM
kernelBinning->unserialize(cp, section);
kernelSymtab->unserialize("kernel_symtab", cp, section);
+#endif // FULL_SYSTEM
}
void
@@ -181,5 +231,35 @@ printSystems()
System::printSystems();
}
+#if FULL_SYSTEM
+
+// In full system mode, only derived classes (e.g. AlphaLinuxSystem)
+// can be created directly.
+
DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
+#else
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
+
+ SimObjectParam<PhysicalMemory *> physmem;
+
+END_DECLARE_SIM_OBJECT_PARAMS(System)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(System)
+
+ INIT_PARAM(physmem, "physical memory")
+
+END_INIT_SIM_OBJECT_PARAMS(System)
+
+CREATE_SIM_OBJECT(System)
+{
+ System::Params *p = new System::Params;
+ p->name = getInstanceName();
+ p->physmem = physmem;
+ return new System(p);
+}
+
+REGISTER_SIM_OBJECT("System", System)
+
+#endif
diff --git a/sim/system.hh b/sim/system.hh
index ea482a102..7e21bd587 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -32,30 +32,34 @@
#include <string>
#include <vector>
-#include "base/statistics.hh"
#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
#include "cpu/pc_event.hh"
-#include "kern/system_events.hh"
+#include "mem/port.hh"
#include "sim/sim_object.hh"
+#if FULL_SYSTEM
+#include "kern/system_events.hh"
+#include "mem/vport.hh"
+#endif
class BaseCPU;
class ExecContext;
-class GDBListener;
-class MemoryController;
class ObjectFile;
class PhysicalMemory;
+
+#if FULL_SYSTEM
class Platform;
+class GDBListener;
class RemoteGDB;
namespace Kernel { class Binning; }
+#endif
class System : public SimObject
{
public:
- MemoryController *memctrl;
PhysicalMemory *physmem;
- Platform *platform;
PCEventQueue pcEventQueue;
- uint64_t init_param;
std::vector<ExecContext *> execContexts;
int numcpus;
@@ -68,6 +72,15 @@ class System : public SimObject
return numcpus;
}
+#if FULL_SYSTEM
+ Platform *platform;
+ uint64_t init_param;
+
+ /** Port to physical memory used for writing object files into ram at
+ * boot.*/
+ FunctionalPort functionalPort;
+ VirtualPort virtPort;
+
/** kernel symbol table */
SymbolTable *kernelSymtab;
@@ -85,8 +98,16 @@ class System : public SimObject
Kernel::Binning *kernelBinning;
+#else
+
+ int page_ptr;
+
+
+#endif // FULL_SYSTEM
+
protected:
+#if FULL_SYSTEM
/**
* Fix up an address used to match PCs for hooking simulator
* events on to target function executions. See comment in
@@ -118,18 +139,23 @@ class System : public SimObject
return addFuncEvent<T>(kernelSymtab, lbl);
}
+#endif
public:
+#if FULL_SYSTEM
std::vector<RemoteGDB *> remoteGDB;
std::vector<GDBListener *> gdbListen;
virtual bool breakpoint() = 0;
+#endif // FULL_SYSTEM
public:
struct Params
{
std::string name;
- Tick boot_cpu_frequency;
- MemoryController *memctrl;
PhysicalMemory *physmem;
+
+#if FULL_SYSTEM
+ Tick boot_cpu_frequency;
+ std::string boot_osflags;
uint64_t init_param;
bool bin;
std::vector<std::string> binned_fns;
@@ -137,6 +163,7 @@ class System : public SimObject
std::string kernel_path;
std::string readfile;
+#endif
};
protected:
@@ -151,6 +178,8 @@ class System : public SimObject
const Params *params() const { return (const Params *)_params; }
public:
+
+#if FULL_SYSTEM
/**
* Returns the addess the kernel starts at.
* @return address the kernel starts at
@@ -169,6 +198,12 @@ class System : public SimObject
*/
Addr getKernelEntry() const { return kernelEntry; }
+#else
+
+ Addr new_page();
+
+#endif // FULL_SYSTEM
+
int registerExecContext(ExecContext *xc, int xcIndex);
void replaceExecContext(ExecContext *xc, int xcIndex);
diff --git a/sim/vptr.hh b/sim/vptr.hh
index 0ec452f25..cc57e63f0 100644
--- a/sim/vptr.hh
+++ b/sim/vptr.hh
@@ -96,20 +96,26 @@ class VPtr
operator T *()
{
- void *addr = vtomem(xc, ptr, sizeof(T));
+ panic("Needs to be rewritten\n");
+/* void *addr = vtomem(xc, ptr, sizeof(T));
return (T *)addr;
+ */
}
T *operator->()
{
- void *addr = vtomem(xc, ptr, sizeof(T));
+ panic("Needs to be rewritten\n");
+/* void *addr = vtomem(xc, ptr, sizeof(T));
return (T *)addr;
+ */
}
T &operator*()
{
- void *addr = vtomem(xc, ptr, sizeof(T));
+ panic("Needs to be rewritten\n");
+/* void *addr = vtomem(xc, ptr, sizeof(T));
return *(T *)addr;
+ */
}
};
diff --git a/util/qdo b/util/qdo
index 135cce4ef..b3c025720 100755
--- a/util/qdo
+++ b/util/qdo
@@ -179,10 +179,10 @@ try:
if output_dir:
secs_waited = 0
- while not shell.dir_exists(output_dir) and secs_waited < 45:
+ while not shell.dir_exists(output_dir) and secs_waited < 90:
time.sleep(5)
secs_waited += 5
- if secs_waited > 10:
+ if secs_waited > 30:
print "waited", secs_waited, "seconds for", output_dir
# run command